diff options
author | luckytyphlosion <alan.rj.huang@gmail.com> | 2015-05-17 18:21:24 -0400 |
---|---|---|
committer | luckytyphlosion <alan.rj.huang@gmail.com> | 2015-05-17 18:21:24 -0400 |
commit | b5f5a16f43ef62680f09666073f07911306e1561 (patch) | |
tree | b62055647e8b02b8d0341639b398f1ed1a1913a2 | |
parent | fb327a0a949f9ce2f25116c29ee6c9d2aa83bd94 (diff) |
Completed home/overworld.asm with other related functions
-rwxr-xr-x | engine/items/items.asm | 5740 | ||||
-rwxr-xr-x | engine/overworld/map_sprites.asm | 880 | ||||
-rw-r--r-- | home.asm | 9572 | ||||
-rw-r--r-- | home/audio.asm | 369 | ||||
-rw-r--r-- | home/init.asm | 273 | ||||
-rw-r--r-- | home/overworld.asm | 4518 | ||||
-rw-r--r-- | macros.asm | 1169 | ||||
-rwxr-xr-x | main.asm | 13368 | ||||
-rwxr-xr-x | wram.asm | 4602 | ||||
-rw-r--r-- | yellow/bank3c/overworld.asm | 438 | ||||
-rw-r--r-- | yellow/bank3d/random.asm | 30 | ||||
-rw-r--r-- | yellow/bank3f/main.asm | 22 |
12 files changed, 20576 insertions, 20405 deletions
diff --git a/engine/items/items.asm b/engine/items/items.asm index 21e6e924..beb85cde 100755 --- a/engine/items/items.asm +++ b/engine/items/items.asm @@ -1,2868 +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 - jr nc, .notShoreOrWater - ld a, [W_CURMAPTILESET] - cp SHIP_PORT ; Vermilion Dock tileset - ld a, [wTileInFrontOfPlayer] ; tile in front of player - jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset - cp $48 ; eastern shore tile in Safari Zone - jr z, .shoreOrWater - cp $32 ; usual eastern shore tile - jr z, .shoreOrWater -.skipShoreTiles - cp $14 ; water tile - jr z, .shoreOrWater -.notShoreOrWater - scf - ret -.shoreOrWater - and a - ret - -; tilesets with water -WaterTilesets: ; e8e0 (3:68e0) - db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU - 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 df39d112..54312c6f 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"
@@ -1,4781 +1,4791 @@ - -; The rst vectors are unused. -SECTION "rst 00", ROM0 [$00] - rst $38 -SECTION "rst 08", ROM0 [$08] - rst $38 -SECTION "rst 10", ROM0 [$10] - rst $38 -SECTION "rst 18", ROM0 [$18] - rst $38 -SECTION "rst 20", ROM0 [$20] - rst $38 -SECTION "rst 28", ROM0 [$28] - rst $38 -SECTION "rst 30", ROM0 [$30] - rst $38 -SECTION "rst 38", ROM0 [$38] - rst $38 - -; Hardware interrupts -SECTION "vblank", ROM0 [$40] - jp VBlank -SECTION "hblank", ROM0 [$48] - rst $38 -SECTION "timer", ROM0 [$50] - jp Timer -SECTION "serial", ROM0 [$58] - jp Serial -SECTION "joypad", ROM0 [$60] - reti - - -SECTION "Home", ROM0 - -DisableLCD:: - xor a - ld [rIF], a - ld a, [rIE] - ld b, a - res 0, a - ld [rIE], a - -.wait - ld a, [rLY] - cp LY_VBLANK - jr nz, .wait - - ld a, [rLCDC] - and $ff ^ rLCDC_ENABLE_MASK - ld [rLCDC], a - ld a, b - ld [rIE], a - ret - -EnableLCD:: - ld a, [rLCDC] - set rLCDC_ENABLE, a - ld [rLCDC], a - ret - -ClearSprites:: - xor a - ld hl, wOAMBuffer - ld b, 40 * 4 -.loop - ld [hli], a - dec b - jr nz, .loop - ret - -HideSprites:: - ld a, 160 - ld hl, wOAMBuffer - ld de, 4 - ld b, 40 -.loop - ld [hl], a - add hl, de - dec b - jr nz, .loop - ret - -INCLUDE "home/copy.asm" - - - -SECTION "Entry", ROM0 [$100] - - nop - jp Start ; 01ab - - -SECTION "Header", ROM0 [$104] - - ; The header is generated by rgbfix. - ; The space here is allocated to prevent code from being overwritten. - - ds $150 - $104 - - - -SECTION "Main", ROM0 - -Func_150:: ; 0150 (0:0150) - ld a,[H_LOADEDROMBANK] - push af - ld a,b - call BankswitchCommon - ld a,[hli] - ld c,a - ld a,[hli] - ld b,a -.loop - ld a,[hli] - ld d,a - ld a,$3 -.unknownloop - dec a - jr nz,.unknownloop - - rept 7 - call Func_199 - call Func_1a5 - endr - - call Func_199 - dec bc - ld a,c - or b - jr nz,.loop - pop af - call BankswitchCommon - ret - -Func_199:: ; 0199 (0:0199) - ld a,d - and $80 - srl a - srl a - ld [rNR32],a - sla d - ret - -Func_1a5:: ; 01a5 (0:01a5) - ld a,$3 -.unknownloop2 - dec a - jr nz,.unknownloop2 - ret - -Start:: - cp GBC - jr z, .gbc - xor a - jr .ok -.gbc - ld a, $1 -.ok - ld [hGBC], a - jp Init - -Joypad:: ; 01b9 - homecall _Joypad - -ReadJoypad: ; 01c8 (0:01c8) - homecall ReadJoypad_ - -INCLUDE "data/map_header_pointers.asm" -INCLUDE "home/overworld.asm" - - -CheckForUserInterruption:: ; 12f8 (0:12f8) -; Return carry if Up+Select+B, Start or A are pressed in c frames. -; Used only in the intro and title screen. - call DelayFrame - - push bc - call JoypadLowSensitivity - pop bc - - ld a, [hJoyHeld] - cp D_UP + SELECT + B_BUTTON - jr z, .input - - ld a, [hJoy5] - and START | A_BUTTON - jr nz, .input - - dec c - jr nz, CheckForUserInterruption - - and a - ret - -.input - scf - ret - -; function to load position data for destination warp when switching maps -; INPUT: -; a = ID of destination warp within destination map -LoadDestinationWarpPosition:: ; 1313 (0:1313) - ld b,a - ld a,[H_LOADEDROMBANK] - push af - ld a,[wPredefParentBank] - ld [H_LOADEDROMBANK],a - ld [$2000],a - ld a,b - add a - add a - ld c,a - ld b,0 - add hl,bc - ld bc,4 - ld de,wCurrentTileBlockMapViewPointer - call CopyData - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - - -DrawHPBar:: ; 1336 (0:1336) -; Draw an HP bar d tiles long, and fill it to e pixels. -; If c is nonzero, show at least a sliver regardless. -; The right end of the bar changes with [wHPBarType]. - - push hl - push de - push bc - - ; Left - ld a, $71 ; "HP:" - ld [hli], a - ld a, $62 - ld [hli], a - - push hl - - ; Middle - ld a, $63 ; empty -.draw - ld [hli],a - dec d - jr nz, .draw - - ; Right - ld a,[wHPBarType] - dec a - ld a, $6d ; status screen and battle - jr z, .ok - dec a ; pokemon menu -.ok - ld [hl],a - - pop hl - - ld a, e - and a - jr nz, .fill - - ; If c iz nonzero, draw a pixel anyway. - ld a, c - and a - jr z, .done - ld e, 1 - -.fill - ld a, e - sub 8 - jr c, .partial - ld e, a - ld a, $6b ; full - ld [hli], a - ld a, e - and a - jr z, .done - jr .fill - -.partial - ; Fill remaining pixels at the end if necessary. - ld a, $63 ; empty - add e - ld [hl], a -.done - pop bc - pop de - pop hl - ret - - -; loads pokemon data from one of multiple sources to wLoadedMon -; loads base stats to W_MONHDEXNUM -; INPUT: -; [wWhichPokemon] = index of pokemon within party/box -; [wcc49] = source -; 00: player's party -; 01: enemy's party -; 02: current box -; 03: daycare -; OUTPUT: -; [wcf91] = pokemon ID -; wLoadedMon = base address of pokemon data -; W_MONHDEXNUM = base address of base stats -LoadMonData:: ; 1372 (0:1372) - ld hl, LoadMonData_ - ld b, BANK(LoadMonData_) - jp Bankswitch - - -Func_137a:: ; 137a (0:137a) -; Write c to [wMoves + b]. Unused. - ld hl, wMoves - ld e, b - ld d, 0 - add hl, de - ld a, c - ld [hl], a - ret - -LoadFlippedFrontSpriteByMonIndex:: ; 1384 (0:1384) - ld a, 1 - ld [W_SPRITEFLIPPED], a - -LoadFrontSpriteByMonIndex:: ; 1389 (0:1389) - push hl - ld a, [wd11e] - push af - ld a, [wcf91] - ld [wd11e], a - predef IndexToPokedex - ld hl, wd11e - ld a, [hl] - pop bc - ld [hl], b - and a - pop hl - jr z, .invalidDexNumber ; dex #0 invalid - cp NUM_POKEMON + 1 - jr c, .validDexNumber ; dex >#151 invalid -.invalidDexNumber - ld a, RHYDON ; $1 - ld [wcf91], a - ret -.validDexNumber - push hl - ld de, vFrontPic - call LoadMonFrontSprite - pop hl - ld a, [H_LOADEDROMBANK] - push af - ld a, Bank(asm_3f0d0) - ld [H_LOADEDROMBANK], a - ld [$2000], a - xor a - ld [$ffe1], a - call asm_3f0d0 - xor a - ld [W_SPRITEFLIPPED], a - pop af - ld [H_LOADEDROMBANK], a - ld [$2000], a - ret - - -PlayCry:: ; 13d0 (0:13d0) -; Play monster a's cry. - call GetCryData - call PlaySound - jp WaitForSoundToFinish - -GetCryData:: ; 13d9 (0:13d9) -; Load cry data for monster a. - dec a - ld c, a - ld b, 0 - ld hl, CryData - add hl, bc - add hl, bc - add hl, bc - - ld a, Bank(CryData) - call BankswitchHome - ld a, [hli] - ld b, a ; cry id - ld a, [hli] - ld [wc0f1], a - ld a, [hl] - ld [wc0f2], a - call BankswitchBack - - ; Cry headers have 3 channels, - ; and start from index $14, - ; so add 3 times the cry id. - ld a, b - ld c, $14 - rlca ; * 2 - add b - add c - ret - - -DisplayPartyMenu:: ; 13fc (0:13fc) - ld a,[hTilesetType] - push af - xor a - ld [hTilesetType],a - call GBPalWhiteOutWithDelay3 - call ClearSprites - call PartyMenuInit - call DrawPartyMenu - jp HandlePartyMenuInput - -GoBackToPartyMenu:: ; 1411 (0:1411) - ld a,[hTilesetType] - push af - xor a - ld [hTilesetType],a - call PartyMenuInit - call RedrawPartyMenu - jp HandlePartyMenuInput - -PartyMenuInit:: ; 1420 (0:1420) - ld a, 1 ; hardcoded bank - call BankswitchHome - call LoadHpBarAndStatusTilePatterns - ld hl, wd730 - set 6, [hl] ; turn off letter printing delay - xor a - ld [wcc49], a - ld [wcc37], a - ld hl, wTopMenuItemY - inc a - ld [hli], a ; top menu item Y - xor a - ld [hli], a ; top menu item X - ld a, [wcc2b] - push af - ld [hli], a ; current menu item ID - inc hl - ld a, [wPartyCount] - and a ; are there more than 0 pokemon in the party? - jr z, .storeMaxMenuItemID - dec a -; if party is not empty, the max menu item ID is ([wPartyCount] - 1) -; otherwise, it is 0 -.storeMaxMenuItemID - ld [hli], a ; max menu item ID - ld a, [wd11f] - and a - ld a, A_BUTTON + B_BUTTON - jr z, .next - xor a - ld [wd11f], a - inc a -.next - ld [hli], a ; menu watched keys - pop af - ld [hl], a ; old menu item ID - ret - -HandlePartyMenuInput:: ; 145a (0:145a) - ld a,1 - ld [wMenuWrappingEnabled],a - ld a,$40 - ld [wd09b],a - call HandleMenuInputPokemonSelection - call PlaceUnfilledArrowMenuCursor - ld b,a - xor a - ld [wd09b],a - ld a,[wCurrentMenuItem] - ld [wcc2b],a - ld hl,wd730 - res 6,[hl] ; turn on letter printing delay - ld a,[wMenuItemToSwap] - and a - jp nz,.swappingPokemon - pop af - ld [hTilesetType],a - bit 1,b - jr nz,.noPokemonChosen - ld a,[wPartyCount] - and a - jr z,.noPokemonChosen - ld a,[wCurrentMenuItem] - ld [wWhichPokemon],a - ld hl,wPartySpecies - ld b,0 - ld c,a - add hl,bc - ld a,[hl] - ld [wcf91],a - ld [wBattleMonSpecies2],a - call BankswitchBack - and a - ret -.noPokemonChosen - call BankswitchBack - scf - ret -.swappingPokemon - bit 1,b ; was the B button pressed? - jr z,.handleSwap ; if not, handle swapping the pokemon -.cancelSwap ; if the B button was pressed - callba ErasePartyMenuCursors - xor a - ld [wMenuItemToSwap],a - ld [wd07d],a - call RedrawPartyMenu - jr HandlePartyMenuInput -.handleSwap - ld a,[wCurrentMenuItem] - ld [wWhichPokemon],a - callba SwitchPartyMon - jr HandlePartyMenuInput - -DrawPartyMenu:: ; 14d4 (0:14d4) - ld hl, DrawPartyMenu_ - jr DrawPartyMenuCommon - -RedrawPartyMenu:: ; 14d9 (0:14d9) - ld hl, RedrawPartyMenu_ - -DrawPartyMenuCommon:: ; 14dc (0:14dc) - ld b, BANK(RedrawPartyMenu_) - jp Bankswitch - -; prints a pokemon's status condition -; INPUT: -; de = address of status condition -; hl = destination address -PrintStatusCondition:: ; 14e1 (0:14e1) - push de - dec de - dec de ; de = address of current HP - ld a,[de] - ld b,a - dec de - ld a,[de] - or b ; is the pokemon's HP zero? - pop de - jr nz,PrintStatusConditionNotFainted -; if the pokemon's HP is 0, print "FNT" - ld a,"F" - ld [hli],a - ld a,"N" - ld [hli],a - ld [hl],"T" - and a - ret -PrintStatusConditionNotFainted ; 14f6 - ld a,[H_LOADEDROMBANK] - push af - ld a,BANK(PrintStatusAilment) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call PrintStatusAilment ; print status condition - pop bc - ld a,b - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; function to print pokemon level, leaving off the ":L" if the level is at least 100 -; INPUT: -; hl = destination address -; [wLoadedMonLevel] = level -PrintLevel:: ; 150b (0:150b) - ld a,$6e ; ":L" tile ID - ld [hli],a - ld c,2 ; number of digits - ld a,[wLoadedMonLevel] ; level - cp a,100 - jr c,PrintLevelCommon -; if level at least 100, write over the ":L" tile - dec hl - inc c ; increment number of digits to 3 - jr PrintLevelCommon - -; prints the level without leaving off ":L" regardless of level -; INPUT: -; hl = destination address -; [wLoadedMonLevel] = level -PrintLevelFull:: ; 151b (0:151b) - ld a,$6e ; ":L" tile ID - ld [hli],a - ld c,3 ; number of digits - ld a,[wLoadedMonLevel] ; level - -PrintLevelCommon:: ; 1523 (0:1523) - ld [wd11e],a - ld de,wd11e - ld b,$41 ; no leading zeroes, left-aligned, one byte - jp PrintNumber - -Func_152e:: ; 152e (0:152e) -; Unused. - ld hl,wMoves - ld c,a - ld b,0 - add hl,bc - ld a,[hl] - ret - -; copies the base stat data of a pokemon to W_MONHDEXNUM (W_MONHEADER) -; INPUT: -; [wd0b5] = pokemon ID -GetMonHeader:: ; 1537 (0:1537) - ld a,[H_LOADEDROMBANK] - push af - ld a,BANK(BaseStats) - ld [H_LOADEDROMBANK],a - ld [$2000],a - push bc - push de - push hl - ld a,[wd11e] - push af - ld a,[wd0b5] - ld [wd11e],a - ld de,FossilKabutopsPic - ld b,$66 ; size of Kabutops fossil and Ghost sprites - cp a,FOSSIL_KABUTOPS ; Kabutops fossil - jr z,.specialID - ld de,GhostPic - cp a,MON_GHOST ; Ghost - jr z,.specialID - ld de,FossilAerodactylPic - ld b,$77 ; size of Aerodactyl fossil sprite - cp a,FOSSIL_AERODACTYL ; Aerodactyl fossil - jr z,.specialID - cp a,MEW - jr z,.mew - predef IndexToPokedex ; convert pokemon ID in [wd11e] to pokedex number - ld a,[wd11e] - dec a - ld bc,28 - ld hl,BaseStats - call AddNTimes - ld de,W_MONHEADER - ld bc,28 - call CopyData - jr .done -.specialID - ld hl,W_MONHSPRITEDIM - ld [hl],b ; write sprite dimensions - inc hl - ld [hl],e ; write front sprite pointer - inc hl - ld [hl],d - jr .done -.mew - ld hl,MewBaseStats - ld de,W_MONHEADER - ld bc,28 - ld a,BANK(MewBaseStats) - call FarCopyData -.done - ld a,[wd0b5] - ld [W_MONHDEXNUM],a - pop af - ld [wd11e],a - pop hl - pop de - pop bc - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; copy party pokemon's name to wcd6d -GetPartyMonName2:: ; 15b4 (0:15b4) - ld a,[wWhichPokemon] ; index within party - ld hl,wPartyMonNicks - -; this is called more often -GetPartyMonName:: ; 15ba (0:15ba) - push hl - push bc - call SkipFixedLengthTextEntries ; add 11 to hl, a times - ld de,wcd6d - push de - ld bc,11 - call CopyData - pop de - pop bc - pop hl - ret - -; function to print a BCD (Binary-coded decimal) number -; de = address of BCD number -; hl = destination address -; c = flags and length -; bit 7: if set, do not print leading zeroes -; if unset, print leading zeroes -; bit 6: if set, left-align the string (do not pad empty digits with spaces) -; if unset, right-align the string -; bit 5: if set, print currency symbol at the beginning of the string -; if unset, do not print the currency symbol -; bits 0-4: length of BCD number in bytes -; Note that bits 5 and 7 are modified during execution. The above reflects -; their meaning at the beginning of the functions's execution. -PrintBCDNumber:: ; 15cd (0:15cd) - ld b,c ; save flags in b - res 7,c - res 6,c - res 5,c ; c now holds the length - bit 5,b - jr z,.loop - bit 7,b - jr nz,.loop - ld [hl],"¥" - inc hl -.loop - ld a,[de] - swap a - call PrintBCDDigit ; print upper digit - ld a,[de] - call PrintBCDDigit ; print lower digit - inc de - dec c - jr nz,.loop - bit 7,b ; were any non-zero digits printed? - jr z,.done ; if so, we are done -.numberEqualsZero ; if every digit of the BCD number is zero - bit 6,b ; left or right alignment? - jr nz,.skipRightAlignmentAdjustment - dec hl ; if the string is right-aligned, it needs to be moved back one space -.skipRightAlignmentAdjustment - bit 5,b - jr z,.skipCurrencySymbol - ld [hl],"¥" - inc hl -.skipCurrencySymbol - ld [hl],"0" - call PrintLetterDelay - inc hl -.done - ret - -PrintBCDDigit:: ; 1604 (0:1604) - and $f - and a - jr z,.zeroDigit -.nonzeroDigit - bit 7,b ; have any non-space characters been printed? - jr z,.outputDigit -; if bit 7 is set, then no numbers have been printed yet - bit 5,b ; print the currency symbol? - jr z,.skipCurrencySymbol - ld [hl],"¥" - inc hl - res 5,b -.skipCurrencySymbol - res 7,b ; unset 7 to indicate that a nonzero digit has been reached -.outputDigit - add a,"0" - ld [hli],a - jp PrintLetterDelay -.zeroDigit - bit 7,b ; either printing leading zeroes or already reached a nonzero digit? - jr z,.outputDigit ; if so, print a zero digit - bit 6,b ; left or right alignment? - ret nz - inc hl ; if right-aligned, "print" a space by advancing the pointer - ret - -; uncompresses the front or back sprite of the specified mon -; assumes the corresponding mon header is already loaded -; hl contains offset to sprite pointer ($b for front or $d for back) -UncompressMonSprite:: ; 1627 (0:1627) - ld bc,W_MONHEADER - add hl,bc - ld a,[hli] - ld [W_SPRITEINPUTPTR],a ; fetch sprite input pointer - ld a,[hl] - ld [W_SPRITEINPUTPTR+1],a -; define (by index number) the bank that a pokemon's image is in -; index = Mew, bank 1 -; index = Kabutops fossil, bank $B -; index < $1F, bank 9 -; $1F ≤ index < $4A, bank $A -; $4A ≤ index < $74, bank $B -; $74 ≤ index < $99, bank $C -; $99 ≤ index, bank $D - ld a,[wcf91] ; XXX name for this ram location - ld b,a - cp MEW - ld a,BANK(MewPicFront) - jr z,.GotBank - ld a,b - cp FOSSIL_KABUTOPS - ld a,BANK(FossilKabutopsPic) - jr z,.GotBank - ld a,b - cp TANGELA + 1 - ld a,BANK(TangelaPicFront) - jr c,.GotBank - ld a,b - cp MOLTRES + 1 - ld a,BANK(MoltresPicFront) - jr c,.GotBank - ld a,b - cp BEEDRILL + 2 - ld a,BANK(BeedrillPicFront) - jr c,.GotBank - ld a,b - cp STARMIE + 1 - ld a,BANK(StarmiePicFront) - jr c,.GotBank - ld a,BANK(VictreebelPicFront) -.GotBank - jp UncompressSpriteData - -; de: destination location -LoadMonFrontSprite:: ; 1665 (0:1665) - push de - ld hl, W_MONHFRONTSPRITE - W_MONHEADER - call UncompressMonSprite - ld hl, W_MONHSPRITEDIM - ld a, [hli] - ld c, a - pop de - ; fall through - -; postprocesses uncompressed sprite chunks to a 2bpp sprite and loads it into video ram -; calculates alignment parameters to place both sprite chunks in the center of the 7*7 tile sprite buffers -; de: destination location -; a,c: sprite dimensions (in tiles of 8x8 each) -LoadUncompressedSpriteData:: ; 1672 (0:1672) - push de - and $f - ld [H_SPRITEWIDTH], a ; each byte contains 8 pixels (in 1bpp), so tiles=bytes for width - ld b, a - ld a, $7 - sub b ; 7-w - inc a ; 8-w - srl a ; (8-w)/2 ; horizontal center (in tiles, rounded up) - ld b, a - add a - add a - add a - sub b ; 7*((8-w)/2) ; skip for horizontal center (in tiles) - ld [H_SPRITEOFFSET], a - ld a, c - swap a - and $f - ld b, a - add a - add a - add a ; 8*tiles is height in bytes - ld [H_SPRITEHEIGHT], a ; $ff8c - ld a, $7 - sub b ; 7-h ; skip for vertical center (in tiles, relative to current column) - ld b, a - ld a, [H_SPRITEOFFSET] - add b ; 7*((8-w)/2) + 7-h ; combined overall offset (in tiles) - add a - add a - add a ; 8*(7*((8-w)/2) + 7-h) ; combined overall offset (in bytes) - ld [H_SPRITEOFFSET], a - xor a - ld [$4000], a - ld hl, S_SPRITEBUFFER0 - call ZeroSpriteBuffer ; zero buffer 0 - ld de, S_SPRITEBUFFER1 - ld hl, S_SPRITEBUFFER0 - call AlignSpriteDataCentered ; copy and align buffer 1 to 0 (containing the MSB of the 2bpp sprite) - ld hl, S_SPRITEBUFFER1 - call ZeroSpriteBuffer ; zero buffer 1 - ld de, S_SPRITEBUFFER2 - ld hl, S_SPRITEBUFFER1 - call AlignSpriteDataCentered ; copy and align buffer 2 to 1 (containing the LSB of the 2bpp sprite) - pop de - jp InterlaceMergeSpriteBuffers - -; copies and aligns the sprite data properly inside the sprite buffer -; sprite buffers are 7*7 tiles in size, the loaded sprite is centered within this area -AlignSpriteDataCentered:: ; 16c2 (0:16c2) - ld a, [H_SPRITEOFFSET] - ld b, $0 - ld c, a - add hl, bc - ld a, [H_SPRITEWIDTH] ; $ff8b -.columnLoop - push af - push hl - ld a, [H_SPRITEHEIGHT] ; $ff8c - ld c, a -.columnInnerLoop - ld a, [de] - inc de - ld [hli], a - dec c - jr nz, .columnInnerLoop - pop hl - ld bc, 7*8 ; 7 tiles - add hl, bc ; advance one full column - pop af - dec a - jr nz, .columnLoop - ret - -; fills the sprite buffer (pointed to in hl) with zeros -ZeroSpriteBuffer:: ; 16df (0:16df) - ld bc, SPRITEBUFFERSIZE -.nextByteLoop - xor a - ld [hli], a - dec bc - ld a, b - or c - jr nz, .nextByteLoop - ret - -; combines the (7*7 tiles, 1bpp) sprite chunks in buffer 0 and 1 into a 2bpp sprite located in buffer 1 through 2 -; in the resulting sprite, the rows of the two source sprites are interlaced -; de: output address -InterlaceMergeSpriteBuffers:: ; 16ea (0:16ea) - xor a - ld [$4000], a - push de - ld hl, S_SPRITEBUFFER2 + (SPRITEBUFFERSIZE - 1) ; destination: end of buffer 2 - ld de, S_SPRITEBUFFER1 + (SPRITEBUFFERSIZE - 1) ; source 2: end of buffer 1 - ld bc, S_SPRITEBUFFER0 + (SPRITEBUFFERSIZE - 1) ; source 1: end of buffer 0 - ld a, SPRITEBUFFERSIZE/2 ; $c4 - ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b -.interlaceLoop - ld a, [de] - dec de - ld [hld], a ; write byte of source 2 - ld a, [bc] - dec bc - ld [hld], a ; write byte of source 1 - ld a, [de] - dec de - ld [hld], a ; write byte of source 2 - ld a, [bc] - dec bc - ld [hld], a ; write byte of source 1 - ld a, [H_SPRITEINTERLACECOUNTER] ; $ff8b - dec a - ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b - jr nz, .interlaceLoop - ld a, [W_SPRITEFLIPPED] - and a - jr z, .notFlipped - ld bc, 2*SPRITEBUFFERSIZE - ld hl, S_SPRITEBUFFER1 -.swapLoop - swap [hl] ; if flipped swap nybbles in all bytes - inc hl - dec bc - ld a, b - or c - jr nz, .swapLoop -.notFlipped - pop hl - ld de, S_SPRITEBUFFER1 - ld c, (2*SPRITEBUFFERSIZE)/16 ; $31, number of 16 byte chunks to be copied - ld a, [H_LOADEDROMBANK] - ld b, a - jp CopyVideoData - - -INCLUDE "data/collision.asm" -INCLUDE "home/copy2.asm" -INCLUDE "home/text.asm" -INCLUDE "home/vcopy.asm" -INCLUDE "home/init.asm" -INCLUDE "home/vblank.asm" -INCLUDE "home/fade.asm" -INCLUDE "home/serial.asm" -INCLUDE "home/timer.asm" -INCLUDE "home/audio.asm" - - -UpdateSprites:: ; 2429 (0:2429) - ld a, [wUpdateSpritesEnabled] - dec a - ret nz - ld a, [H_LOADEDROMBANK] - push af - ld a, Bank(_UpdateSprites) - ld [H_LOADEDROMBANK], a - ld [$2000], a - call _UpdateSprites - pop af - ld [H_LOADEDROMBANK], a - ld [$2000], a - ret - -INCLUDE "data/mart_inventories.asm" - -TextScriptEndingChar:: ; 24d6 (0:24d6) - db "@" -TextScriptEnd:: ; 24d7 (0:24d7) - ld hl,TextScriptEndingChar - ret - -ExclamationText:: ; 24db (0:24db) - TX_FAR _ExclamationText - db "@" - -GroundRoseText:: ; 24e0 (0:24e0) - TX_FAR _GroundRoseText - db "@" - -BoulderText:: ; 24e5 (0:24e5) - TX_FAR _BoulderText - db "@" - -MartSignText:: ; 24ea (0:24ea) - TX_FAR _MartSignText - db "@" - -PokeCenterSignText:: ; 24ef (0:24ef) - TX_FAR _PokeCenterSignText - db "@" - -Predef5CText:: ; 24f4 (0:24f4) -; XXX better label (what does predef $5C do?) - db $08 ; asm - predef PickupItem - jp TextScriptEnd - - -INCLUDE "home/pic.asm" - - -ResetPlayerSpriteData:: ; 28a6 (0:28a6) - ld hl, wSpriteStateData1 - call ResetPlayerSpriteData_ClearSpriteData - ld hl, wSpriteStateData2 - call ResetPlayerSpriteData_ClearSpriteData - ld a, $1 - ld [wSpriteStateData1], a - ld [wSpriteStateData2 + $0e], a - ld hl, wSpriteStateData1 + 4 - ld [hl], $3c ; set Y screen pos - inc hl - inc hl - ld [hl], $40 ; set X screen pos - ret - -; overwrites sprite data with zeroes -ResetPlayerSpriteData_ClearSpriteData:: ; 28c4 (0:28c4) - ld bc, $10 - xor a - jp FillMemory - -Func_28cb:: ; 28cb (0:28cb) - ld a, [wMusicHeaderPointer] - and a - jr nz, .asm_28dc - ld a, [wd72c] - bit 1, a - ret nz - ld a, $77 - ld [$ff24], a - ret -.asm_28dc - ld a, [wcfc9] - and a - jr z, .asm_28e7 - dec a - ld [wcfc9], a - ret -.asm_28e7 - ld a, [wcfc8] - ld [wcfc9], a - ld a, [$ff24] - and a - jr z, .asm_2903 - ld b, a - and $f - dec a - ld c, a - ld a, b - and $f0 - swap a - dec a - swap a - or c - ld [$ff24], a - ret -.asm_2903 - ld a, [wMusicHeaderPointer] - ld b, a - xor a - ld [wMusicHeaderPointer], a - ld a, $ff - ld [wc0ee], a - call PlaySound - ld a, [wc0f0] - ld [wc0ef], a - ld a, b - ld [wc0ee], a - jp PlaySound - -; this function is used to display sign messages, sprite dialog, etc. -; INPUT: [$ff8c] = sprite ID or text ID -DisplayTextID:: ; 2920 (0:2920) - ld a,[H_LOADEDROMBANK] - push af - callba DisplayTextIDInit ; initialization - ld hl,wcf11 - bit 0,[hl] - res 0,[hl] - jr nz,.skipSwitchToMapBank - ld a,[W_CURMAP] - call SwitchToMapRomBank -.skipSwitchToMapBank - ld a,30 ; half a second - ld [H_FRAMECOUNTER],a ; used as joypad poll timer - ld hl,W_MAPTEXTPTR - ld a,[hli] - ld h,[hl] - ld l,a ; hl = map text pointer - ld d,$00 - ld a,[$ff8c] ; text ID - ld [wSpriteIndex],a - and a - jp z,DisplayStartMenu - cp a,$d3 - jp z,DisplaySafariGameOverText - cp a,$d0 - jp z,DisplayPokemonFaintedText - cp a,$d1 - jp z,DisplayPlayerBlackedOutText - cp a,$d2 - jp z,DisplayRepelWoreOffText - ld a,[W_NUMSPRITES] - ld e,a - ld a,[$ff8c] ; sprite ID - cp e - jr z,.spriteHandling - jr nc,.skipSpriteHandling -.spriteHandling -; get the text ID of the sprite - push hl - push de - push bc - callba UpdateSpriteFacingOffsetAndDelayMovement ; update the graphics of the sprite the player is talking to (to face the right direction) - pop bc - pop de - ld hl,W_MAPSPRITEDATA ; NPC text entries - ld a,[$ff8c] - dec a - add a - add l - ld l,a - jr nc,.noCarry - inc h -.noCarry - inc hl - ld a,[hl] ; a = text ID of the sprite - pop hl -.skipSpriteHandling -; look up the address of the text in the map's text entries - dec a - ld e,a - sla e - add hl,de - ld a,[hli] - ld h,[hl] - ld l,a ; hl = address of the text - ld a,[hl] ; a = first byte of text -; check first byte of text for special cases - cp a,$fe ; Pokemart NPC - jp z,DisplayPokemartDialogue - cp a,$ff ; Pokemon Center NPC - jp z,DisplayPokemonCenterDialogue - cp a,$fc ; Item Storage PC - jp z,FuncTX_ItemStoragePC - cp a,$fd ; Bill's PC - jp z,FuncTX_BillsPC - cp a,$f9 ; Pokemon Center PC - jp z,FuncTX_PokemonCenterPC - cp a,$f5 ; Vending Machine - jr nz,.notVendingMachine - callba VendingMachineMenu ; jump banks to vending machine routine - jr AfterDisplayingTextID -.notVendingMachine - cp a,$f7 ; slot machine - jp z,FuncTX_SlotMachine - cp a,$f6 ; cable connection NPC in Pokemon Center - jr nz,.notSpecialCase - callab CableClubNPC - jr AfterDisplayingTextID -.notSpecialCase - call Func_3c59 ; display the text - ld a,[wDoNotWaitForButtonPressAfterDisplayingText] - and a - jr nz,HoldTextDisplayOpen - -AfterDisplayingTextID:: ; 29d6 (0:29d6) - ld a,[wcc47] - and a - jr nz,HoldTextDisplayOpen - call WaitForTextScrollButtonPress ; wait for a button press after displaying all the text - -; loop to hold the dialogue box open as long as the player keeps holding down the A button -HoldTextDisplayOpen:: ; 29df (0:29df) - call Joypad - ld a,[hJoyHeld] - bit 0,a ; is the A button being pressed? - jr nz,HoldTextDisplayOpen - -CloseTextDisplay:: ; 29e8 (0:29e8) - ld a,[W_CURMAP] - call SwitchToMapRomBank - ld a,$90 - ld [hWY],a ; move the window off the screen - call DelayFrame - call LoadGBPal - xor a - ld [H_AUTOBGTRANSFERENABLED],a ; disable continuous WRAM to VRAM transfer each V-blank -; loop to make sprites face the directions they originally faced before the dialogue - ld hl,wSpriteStateData2 + $19 - ld c,$0f - ld de,$0010 -.restoreSpriteFacingDirectionLoop - ld a,[hl] - dec h - ld [hl],a - inc h - add hl,de - dec c - jr nz,.restoreSpriteFacingDirectionLoop - ld a,BANK(InitMapSprites) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call InitMapSprites ; reload sprite tile pattern data (since it was partially overwritten by text tile patterns) - ld hl,wFontLoaded - res 0,[hl] - ld a,[wd732] - bit 3,a ; used fly warp - call z,LoadPlayerSpriteGraphics - call LoadCurrentMapView - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - jp UpdateSprites - -DisplayPokemartDialogue:: ; 2a2e (0:2a2e) - push hl - ld hl,PokemartGreetingText - call PrintText - pop hl - inc hl - call LoadItemList - ld a,$02 - ld [wListMenuID],a ; selects between subtypes of menus - ld a,[H_LOADEDROMBANK] - push af - ld a,Bank(DisplayPokemartDialogue_) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call DisplayPokemartDialogue_ - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - jp AfterDisplayingTextID - -PokemartGreetingText:: ; 2a55 (0:2a55) - TX_FAR _PokemartGreetingText - db "@" - -LoadItemList:: ; 2a5a (0:2a5a) - ld a,$01 - ld [wUpdateSpritesEnabled],a - ld a,h - ld [wd128],a - ld a,l - ld [wd129],a - ld de,wStringBuffer2 + 11 -.loop - ld a,[hli] - ld [de],a - inc de - cp a,$ff - jr nz,.loop - ret - -DisplayPokemonCenterDialogue:: ; 2a72 (0:2a72) - xor a - ld [$ff8b],a - ld [$ff8c],a - ld [$ff8d],a - inc hl - ld a,[H_LOADEDROMBANK] - push af - ld a,Bank(DisplayPokemonCenterDialogue_) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call DisplayPokemonCenterDialogue_ - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - jp AfterDisplayingTextID - -DisplaySafariGameOverText:: ; 2a90 (0:2a90) - callab PrintSafariGameOverText - jp AfterDisplayingTextID - -DisplayPokemonFaintedText:: ; 2a9b (0:2a9b) - ld hl,PokemonFaintedText - call PrintText - jp AfterDisplayingTextID - -PokemonFaintedText:: ; 2aa4 (0:2aa4) - TX_FAR _PokemonFaintedText - db "@" - -DisplayPlayerBlackedOutText:: ; 2aa9 (0:2aa9) - ld hl,PlayerBlackedOutText - call PrintText - ld a,[wd732] - res 5,a ; reset forced to use bike bit - ld [wd732],a - jp HoldTextDisplayOpen - -PlayerBlackedOutText:: ; 2aba (0:2aba) - TX_FAR _PlayerBlackedOutText - db "@" - -DisplayRepelWoreOffText:: ; 2abf (0:2abf) - ld hl,RepelWoreOffText - call PrintText - jp AfterDisplayingTextID - -RepelWoreOffText:: ; 2ac8 (0:2ac8) - TX_FAR _RepelWoreOffText - db "@" - -INCLUDE "engine/menu/start_menu.asm" - -; function to count how many bits are set in a string of bytes -; INPUT: -; hl = address of string of bytes -; b = length of string of bytes -; OUTPUT: -; [wd11e] = number of set bits -CountSetBits:: ; 2b7f (0:2b7f) - ld c,0 -.loop - ld a,[hli] - ld e,a - ld d,8 -.innerLoop ; count how many bits are set in the current byte - srl e - ld a,0 - adc c - ld c,a - dec d - jr nz,.innerLoop - dec b - jr nz,.loop - ld a,c - ld [wd11e],a ; store number of set bits - ret - -; subtracts the amount the player paid from their money -; sets carry flag if there is enough money and unsets carry flag if not -SubtractAmountPaidFromMoney:: ; 2b96 (0:2b96) - ld b,BANK(SubtractAmountPaidFromMoney_) - ld hl,SubtractAmountPaidFromMoney_ - jp Bankswitch - -; adds the amount the player sold to their money -AddAmountSoldToMoney:: ; 2b9e (0:2b9e) - ld de,wPlayerMoney + 2 - ld hl,$ffa1 ; total price of items - ld c,3 ; length of money in bytes - predef AddBCDPredef ; add total price to money - ld a,MONEY_BOX - ld [wTextBoxID],a - call DisplayTextBoxID ; redraw money text box - ld a, (SFX_02_5a - SFX_Headers_02) / 3 - call PlaySoundWaitForCurrent ; play sound - jp WaitForSoundToFinish ; wait until sound is done playing - -; function to remove an item (in varying quantities) from the player's bag or PC box -; INPUT: -; HL = address of inventory (either wNumBagItems or wNumBoxItems) -; [wWhichPokemon] = index (within the inventory) of the item to remove -; [wcf96] = quantity to remove -RemoveItemFromInventory:: ; 2bbb (0:2bbb) - ld a,[H_LOADEDROMBANK] - push af - ld a,BANK(RemoveItemFromInventory_) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call RemoveItemFromInventory_ - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; function to add an item (in varying quantities) to the player's bag or PC box -; INPUT: -; HL = address of inventory (either wNumBagItems or wNumBoxItems) -; [wcf91] = item ID -; [wcf96] = item quantity -; sets carry flag if successful, unsets carry flag if unsuccessful -AddItemToInventory:: ; 2bcf (0:2bcf) - push bc - ld a,[H_LOADEDROMBANK] - push af - ld a,BANK(AddItemToInventory_) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call AddItemToInventory_ - pop bc - ld a,b - ld [H_LOADEDROMBANK],a - ld [$2000],a - pop bc - ret - -; INPUT: -; [wListMenuID] = list menu ID -; [wList] = address of the list (2 bytes) -DisplayListMenuID:: ; 2be6 (0:2be6) - xor a - ld [H_AUTOBGTRANSFERENABLED],a ; disable auto-transfer - ld a,1 - ld [hJoy7],a ; joypad state update flag - ld a,[W_BATTLETYPE] - and a ; is it the Old Man battle? - jr nz,.specialBattleType - ld a,$01 ; hardcoded bank - jr .bankswitch -.specialBattleType ; Old Man battle - ld a, Bank(DisplayBattleMenu) -.bankswitch - call BankswitchHome - ld hl,wd730 - set 6,[hl] ; turn off letter printing delay - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - ld [wd12a],a - ld a,[wList] - ld l,a - ld a,[wList + 1] - ld h,a ; hl = address of the list - ld a,[hl] - ld [wd12a],a ; [wd12a] = number of list entries - ld a,LIST_MENU_BOX - ld [wTextBoxID],a - call DisplayTextBoxID ; draw the menu text box - call UpdateSprites ; disable sprites behind the text box -; the code up to .skipMovingSprites appears to be useless - hlCoord 4, 2 ; coordinates of upper left corner of menu text box - ld de,$090e ; height and width of menu text box - ld a,[wListMenuID] - and a ; is it a PC pokemon list? - jr nz,.skipMovingSprites - call UpdateSprites ; move sprites -.skipMovingSprites - ld a,1 ; max menu item ID is 1 if the list has less than 2 entries - ld [wcc37],a - ld a,[wd12a] - cp a,2 ; does the list have less than 2 entries? - jr c,.setMenuVariables - ld a,2 ; max menu item ID is 2 if the list has at least 2 entries -.setMenuVariables - ld [wMaxMenuItem],a - ld a,4 - ld [wTopMenuItemY],a - ld a,5 - ld [wTopMenuItemX],a - ld a,A_BUTTON | B_BUTTON | SELECT - ld [wMenuWatchedKeys],a - ld c,10 - call DelayFrames - -DisplayListMenuIDLoop:: ; 2c53 (0:2c53) - xor a - ld [H_AUTOBGTRANSFERENABLED],a ; disable transfer - call PrintListMenuEntries - ld a,1 - ld [H_AUTOBGTRANSFERENABLED],a ; enable transfer - call Delay3 - ld a,[W_BATTLETYPE] - and a ; is it the Old Man battle? - jr z,.notOldManBattle -.oldManBattle - ld a,"▶" - Coorda 5, 4 ; place menu cursor in front of first menu entry - ld c,80 - call DelayFrames - xor a - ld [wCurrentMenuItem],a - hlCoord 5, 4 - ld a,l - ld [wMenuCursorLocation],a - ld a,h - ld [wMenuCursorLocation + 1],a - jr .buttonAPressed -.notOldManBattle - call LoadGBPal - call HandleMenuInput - push af - call PlaceMenuCursor - pop af - bit 0,a ; was the A button pressed? - jp z,.checkOtherKeys -.buttonAPressed - ld a,[wCurrentMenuItem] - call PlaceUnfilledArrowMenuCursor - ld a,$01 - ld [wd12e],a - ld [wd12d],a - xor a - ld [wcc37],a - ld a,[wCurrentMenuItem] - ld c,a - ld a,[wListScrollOffset] - add c - ld c,a - ld a,[wd12a] ; number of list entries - and a ; is the list empty? - jp z,ExitListMenu ; if so, exit the menu - dec a - cp c ; did the player select Cancel? - jp c,ExitListMenu ; if so, exit the menu - ld a,c - ld [wWhichPokemon],a - ld a,[wListMenuID] - cp a,ITEMLISTMENU - jr nz,.skipMultiplying -; if it's an item menu - sla c ; item entries are 2 bytes long, so multiply by 2 -.skipMultiplying - ld a,[wList] - ld l,a - ld a,[wList + 1] - ld h,a - inc hl ; hl = beginning of list entries - ld b,0 - add hl,bc - ld a,[hl] - ld [wcf91],a - ld a,[wListMenuID] - and a ; is it a PC pokemon list? - jr z,.pokemonList - push hl - call GetItemPrice - pop hl - ld a,[wListMenuID] - cp a,ITEMLISTMENU - jr nz,.skipGettingQuantity -; if it's an item menu - inc hl - ld a,[hl] ; a = item quantity - ld [wcf97],a -.skipGettingQuantity - ld a,[wcf91] - ld [wd0b5],a - ld a,BANK(ItemNames) - ld [wPredefBank],a - call GetName - jr .storeChosenEntry -.pokemonList - ld hl,wPartyCount - ld a,[wList] - cp l ; is it a list of party pokemon or box pokemon? - ld hl,wPartyMonNicks - jr z,.getPokemonName - ld hl, wBoxMonNicks ; box pokemon names -.getPokemonName - ld a,[wWhichPokemon] - call GetPartyMonName -.storeChosenEntry ; store the menu entry that the player chose and return - ld de,wcd6d - call CopyStringToCF4B ; copy name to wcf4b - ld a,$01 - ld [wd12e],a - ld a,[wCurrentMenuItem] - ld [wd12d],a - xor a - ld [hJoy7],a ; joypad state update flag - ld hl,wd730 - res 6,[hl] ; turn on letter printing delay - jp BankswitchBack -.checkOtherKeys ; check B, SELECT, Up, and Down keys - bit 1,a ; was the B button pressed? - jp nz,ExitListMenu ; if so, exit the menu - bit 2,a ; was the select button pressed? - jp nz,HandleItemListSwapping ; if so, allow the player to swap menu entries - ld b,a - bit 7,b ; was Down pressed? - ld hl,wListScrollOffset - jr z,.upPressed -.downPressed - ld a,[hl] - add a,3 - ld b,a - ld a,[wd12a] ; number of list entries - cp b ; will going down scroll past the Cancel button? - jp c,DisplayListMenuIDLoop - inc [hl] ; if not, go down - jp DisplayListMenuIDLoop -.upPressed - ld a,[hl] - and a - jp z,DisplayListMenuIDLoop - dec [hl] - jp DisplayListMenuIDLoop - -DisplayChooseQuantityMenu:: ; 2d57 (0:2d57) -; text box dimensions/coordinates for just quantity - hlCoord 15, 9 - ld b,1 ; height - ld c,3 ; width - ld a,[wListMenuID] - cp a,PRICEDITEMLISTMENU - jr nz,.drawTextBox -; text box dimensions/coordinates for quantity and price - hlCoord 7, 9 - ld b,1 ; height - ld c,11 ; width -.drawTextBox - call TextBoxBorder - hlCoord 16, 10 - ld a,[wListMenuID] - cp a,PRICEDITEMLISTMENU - jr nz,.printInitialQuantity - hlCoord 8, 10 -.printInitialQuantity - ld de,InitialQuantityText - call PlaceString - xor a - ld [wcf96],a ; initialize current quantity to 0 - jp .incrementQuantity -.waitForKeyPressLoop - call JoypadLowSensitivity - ld a,[hJoyPressed] ; newly pressed buttons - bit 0,a ; was the A button pressed? - jp nz,.buttonAPressed - bit 1,a ; was the B button pressed? - jp nz,.buttonBPressed - bit 6,a ; was Up pressed? - jr nz,.incrementQuantity - bit 7,a ; was Down pressed? - jr nz,.decrementQuantity - jr .waitForKeyPressLoop -.incrementQuantity - ld a,[wcf97] ; max quantity - inc a - ld b,a - ld hl,wcf96 ; current quantity - inc [hl] - ld a,[hl] - cp b - jr nz,.handleNewQuantity -; wrap to 1 if the player goes above the max quantity - ld a,1 - ld [hl],a - jr .handleNewQuantity -.decrementQuantity - ld hl,wcf96 ; current quantity - dec [hl] - jr nz,.handleNewQuantity -; wrap to the max quantity if the player goes below 1 - ld a,[wcf97] ; max quantity - ld [hl],a -.handleNewQuantity - hlCoord 17, 10 - ld a,[wListMenuID] - cp a,PRICEDITEMLISTMENU - jr nz,.printQuantity -.printPrice - ld c,$03 - ld a,[wcf96] - ld b,a - ld hl,$ff9f ; total price -; initialize total price to 0 - xor a - ld [hli],a - ld [hli],a - ld [hl],a -.addLoop ; loop to multiply the individual price by the quantity to get the total price - ld de,$ffa1 - ld hl,$ff8d - push bc - predef AddBCDPredef ; add the individual price to the current sum - pop bc - dec b - jr nz,.addLoop - ld a,[$ff8e] - and a ; should the price be halved (for selling items)? - jr z,.skipHalvingPrice - xor a - ld [$ffa2],a - ld [$ffa3],a - ld a,$02 - ld [$ffa4],a - predef DivideBCDPredef3 ; halves the price -; store the halved price - ld a,[$ffa2] - ld [$ff9f],a - ld a,[$ffa3] - ld [$ffa0],a - ld a,[$ffa4] - ld [$ffa1],a -.skipHalvingPrice - hlCoord 12, 10 - ld de,SpacesBetweenQuantityAndPriceText - call PlaceString - ld de,$ff9f ; total price - ld c,$a3 - call PrintBCDNumber - hlCoord 9, 10 -.printQuantity - ld de,wcf96 ; current quantity - ld bc,$8102 ; print leading zeroes, 1 byte, 2 digits - call PrintNumber - jp .waitForKeyPressLoop -.buttonAPressed ; the player chose to make the transaction - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - ret -.buttonBPressed ; the player chose to cancel the transaction - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - ld a,$ff - ret - -InitialQuantityText:: ; 2e30 (0:2e30) - db "×01@" - -SpacesBetweenQuantityAndPriceText:: ; 2e34 (0:2e34) - db " @" - -ExitListMenu:: ; 2e3b (0:2e3b) - ld a,[wCurrentMenuItem] - ld [wd12d],a - ld a,$02 - ld [wd12e],a - ld [wcc37],a - xor a - ld [hJoy7],a - ld hl,wd730 - res 6,[hl] - call BankswitchBack - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - scf - ret - -PrintListMenuEntries:: ; 2e5a (0:2e5a) - hlCoord 5, 3 - ld b,$09 - ld c,$0e - call ClearScreenArea - ld a,[wList] - ld e,a - ld a,[wList + 1] - ld d,a - inc de ; de = beginning of list entries - ld a,[wListScrollOffset] - ld c,a - ld a,[wListMenuID] - cp a,ITEMLISTMENU - ld a,c - jr nz,.skipMultiplying -; if it's an item menu -; item entries are 2 bytes long, so multiply by 2 - sla a - sla c -.skipMultiplying - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry - hlCoord 6, 4 ; coordinates of first list entry name - ld b,4 ; print 4 names -.loop - ld a,b - ld [wWhichPokemon],a - ld a,[de] - ld [wd11e],a - cp a,$ff - jp z,.printCancelMenuItem - push bc - push de - push hl - push hl - push de - ld a,[wListMenuID] - and a - jr z,.pokemonPCMenu - cp a,$01 - jr z,.movesMenu -.itemMenu - call GetItemName - jr .placeNameString -.pokemonPCMenu - push hl - ld hl,wPartyCount - ld a,[wList] - cp l ; is it a list of party pokemon or box pokemon? - ld hl,wPartyMonNicks - jr z,.getPokemonName - ld hl, wBoxMonNicks ; box pokemon names -.getPokemonName - ld a,[wWhichPokemon] - ld b,a - ld a,4 - sub b - ld b,a - ld a,[wListScrollOffset] - add b - call GetPartyMonName - pop hl - jr .placeNameString -.movesMenu - call GetMoveName -.placeNameString - call PlaceString - pop de - pop hl - ld a,[wcf93] - and a ; should prices be printed? - jr z,.skipPrintingItemPrice -.printItemPrice - push hl - ld a,[de] - ld de,ItemPrices - ld [wcf91],a - call GetItemPrice ; get price - pop hl - ld bc,20 + 5 ; 1 row down and 5 columns right - add hl,bc - ld c,$a3 ; no leading zeroes, right-aligned, print currency symbol, 3 bytes - call PrintBCDNumber -.skipPrintingItemPrice - ld a,[wListMenuID] - and a - jr nz,.skipPrintingPokemonLevel -.printPokemonLevel - ld a,[wd11e] - push af - push hl - ld hl,wPartyCount - ld a,[wList] - cp l ; is it a list of party pokemon or box pokemon? - ld a,$00 - jr z,.next - ld a,$02 -.next - ld [wcc49],a - ld hl,wWhichPokemon - ld a,[hl] - ld b,a - ld a,$04 - sub b - ld b,a - ld a,[wListScrollOffset] - add b - ld [hl],a - call LoadMonData ; load pokemon info - ld a,[wcc49] - and a ; is it a list of party pokemon or box pokemon? - jr z,.skipCopyingLevel -.copyLevel - ld a,[wLoadedMonBoxLevel] - ld [wLoadedMonLevel],a -.skipCopyingLevel - pop hl - ld bc,$001c - add hl,bc - call PrintLevel ; print level - pop af - ld [wd11e],a -.skipPrintingPokemonLevel - pop hl - pop de - inc de - ld a,[wListMenuID] - cp a,ITEMLISTMENU - jr nz,.nextListEntry -.printItemQuantity - ld a,[wd11e] - ld [wcf91],a - call IsKeyItem ; check if item is unsellable - ld a,[wd124] - and a ; is the item unsellable? - jr nz,.skipPrintingItemQuantity ; if so, don't print the quantity - push hl - ld bc,20 + 8 ; 1 row down and 8 columns right - add hl,bc - ld a,"×" - ld [hli],a - ld a,[wd11e] - push af - ld a,[de] - ld [wcf97],a - push de - ld de,wd11e - ld [de],a - ld bc,$0102 - call PrintNumber - pop de - pop af - ld [wd11e],a - pop hl -.skipPrintingItemQuantity - inc de - pop bc - inc c - push bc - inc c - ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - and a ; is an item being swapped? - jr z,.nextListEntry - sla a - cp c ; is it this item? - jr nz,.nextListEntry - dec hl - ld a,$ec ; unfilled right arrow menu cursor to indicate an item being swapped - ld [hli],a -.nextListEntry - ld bc,2 * 20 ; 2 rows - add hl,bc - pop bc - inc c - dec b - jp nz,.loop - ld bc,-8 - add hl,bc - ld a,$ee ; down arrow - ld [hl],a - ret -.printCancelMenuItem - ld de,ListMenuCancelText - jp PlaceString - -ListMenuCancelText:: ; 2f97 (0:2f97) - db "CANCEL@" - -GetMonName:: ; 2f9e (0:2f9e) - push hl - ld a,[H_LOADEDROMBANK] - push af - ld a,BANK(MonsterNames) ; 07 - ld [H_LOADEDROMBANK],a - ld [$2000],a - ld a,[wd11e] - dec a - ld hl,MonsterNames ; 421E - ld c,10 - ld b,0 - call AddNTimes - ld de,wcd6d - push de - ld bc,10 - call CopyData - ld hl,wcd77 - ld [hl], "@" - pop de - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - pop hl - ret - -GetItemName:: ; 2fcf (0:2fcf) -; given an item ID at [wd11e], store the name of the item into a string -; starting at wcd6d - push hl - push bc - ld a,[wd11e] - cp HM_01 ; is this a TM/HM? - jr nc,.Machine - - ld [wd0b5],a - ld a,ITEM_NAME - ld [wNameListType],a - ld a,BANK(ItemNames) - ld [wPredefBank],a - call GetName - jr .Finish - -.Machine - call GetMachineName -.Finish - ld de,wcd6d ; pointer to where item name is stored in RAM - pop bc - pop hl - ret - -GetMachineName:: ; 2ff3 (0:2ff3) -; copies the name of the TM/HM in [wd11e] to wcd6d - push hl - push de - push bc - ld a,[wd11e] - push af - cp TM_01 ; is this a TM? [not HM] - jr nc,.WriteTM -; if HM, then write "HM" and add 5 to the item ID, so we can reuse the -; TM printing code - add 5 - ld [wd11e],a - ld hl,HiddenPrefix ; points to "HM" - ld bc,2 - jr .WriteMachinePrefix -.WriteTM - ld hl,TechnicalPrefix ; points to "TM" - ld bc,2 -.WriteMachinePrefix - ld de,wcd6d - call CopyData - -; now get the machine number and convert it to text - ld a,[wd11e] - sub TM_01 - 1 - ld b,$F6 ; "0" -.FirstDigit - sub 10 - jr c,.SecondDigit - inc b - jr .FirstDigit -.SecondDigit - add 10 - push af - ld a,b - ld [de],a - inc de - pop af - ld b,$F6 ; "0" - add b - ld [de],a - inc de - ld a,"@" - ld [de],a - - pop af - ld [wd11e],a - pop bc - pop de - pop hl - ret - -TechnicalPrefix:: ; 303c (0:303c) - db "TM" -HiddenPrefix:: ; 303e (0:303e) - db "HM" - -; sets carry if item is HM, clears carry if item is not HM -; Input: a = item ID -IsItemHM:: ; 3040 (0:3040) - cp a,HM_01 - jr c,.notHM - cp a,TM_01 - ret -.notHM - and a - ret - -; sets carry if move is an HM, clears carry if move is not an HM -; Input: a = move ID -IsMoveHM:: ; 3049 (0:3049) - ld hl,HMMoves - ld de,1 - jp IsInArray - -HMMoves:: ; 3052 (0:3052) - db CUT,FLY,SURF,STRENGTH,FLASH - db $ff ; terminator - -GetMoveName:: ; 3058 (0:3058) - push hl - ld a,MOVE_NAME - ld [wNameListType],a - ld a,[wd11e] - ld [wd0b5],a - ld a,BANK(MoveNames) - ld [wPredefBank],a - call GetName - ld de,wcd6d ; pointer to where move name is stored in RAM - pop hl - ret - -; reloads text box tile patterns, current map view, and tileset tile patterns -ReloadMapData:: ; 3071 (0:3071) - ld a,[H_LOADEDROMBANK] - push af - ld a,[W_CURMAP] - call SwitchToMapRomBank - call DisableLCD - call LoadTextBoxTilePatterns - call LoadCurrentMapView - call LoadTilesetTilePatternData - call EnableLCD - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; reloads tileset tile patterns -ReloadTilesetTilePatterns:: ; 3090 (0:3090) - ld a,[H_LOADEDROMBANK] - push af - ld a,[W_CURMAP] - call SwitchToMapRomBank - call DisableLCD - call LoadTilesetTilePatternData - call EnableLCD - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; shows the town map and lets the player choose a destination to fly to -ChooseFlyDestination:: ; 30a9 (0:30a9) - ld hl,wd72e - res 4,[hl] - ld b, BANK(LoadTownMap_Fly) - ld hl, LoadTownMap_Fly - jp Bankswitch - -; causes the text box to close without waiting for a button press after displaying text -DisableWaitingAfterTextDisplay:: ; 30b6 (0:30b6) - ld a,$01 - ld [wDoNotWaitForButtonPressAfterDisplayingText],a - ret - -; uses an item -; UseItem is used with dummy items to perform certain other functions as well -; INPUT: -; [wcf91] = item ID -; OUTPUT: -; [wcd6a] = success -; 00: unsucessful -; 01: successful -; 02: not able to be used right now, no extra menu displayed (only certain items use this) -UseItem:: ; 30bc (0:30bc) - ld b,BANK(UseItem_) - ld hl,UseItem_ - jp Bankswitch - -; 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:: ; 30c4 (0:30c4) - ld a,[H_LOADEDROMBANK] - push af - ld a,BANK(TossItem_) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call TossItem_ - pop de - ld a,d - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; 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:: ; 30d9 (0:30d9) - push hl - push de - push bc - callba IsKeyItem_ - pop bc - pop de - pop hl - ret - -; function to draw various text boxes -; INPUT: -; [wTextBoxID] = text box ID -DisplayTextBoxID:: ; 30e8 (0:30e8) - ld a,[H_LOADEDROMBANK] - push af - ld a,BANK(DisplayTextBoxID_) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call DisplayTextBoxID_ - pop bc - ld a,b - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; not zero if an NPC movement script is running, the player character is -; automatically stepping down from a door, or joypad states are being simulated -IsPlayerCharacterBeingControlledByGame:: ; 30fd (0:30fd) - ld a, [wNPCMovementScriptPointerTableNum] - and a - ret nz - ld a, [wd736] - bit 1, a ; currently stepping down from door bit - ret nz - ld a, [wd730] - and $80 - ret - -RunNPCMovementScript:: ; 310e (0:310e) - ld hl, wd736 - bit 0, [hl] - res 0, [hl] - jr nz, .playerStepOutFromDoor - ld a, [wNPCMovementScriptPointerTableNum] - and a - ret z - dec a - add a - ld d, 0 - ld e, a - ld hl, .NPCMovementScriptPointerTables - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [H_LOADEDROMBANK] - push af - ld a, [wNPCMovementScriptBank] - ld [H_LOADEDROMBANK], a - ld [$2000], a - ld a, [wNPCMovementScriptFunctionNum] - call CallFunctionInTable - pop af - ld [H_LOADEDROMBANK], a - ld [$2000], a - ret -.NPCMovementScriptPointerTables - dw ProfOakMovementScriptPointerTable - dw PewterMuseumGuyMovementScriptPointerTable - dw PewterGymGuyMovementScriptPointerTable -.playerStepOutFromDoor - ld b, BANK(PlayerStepOutFromDoor) - ld hl, PlayerStepOutFromDoor - jp Bankswitch - -EndNPCMovementScript:: ; 314e (0:314e) - ld b, BANK(_EndNPCMovementScript) - ld hl, _EndNPCMovementScript - jp Bankswitch - -EmptyFunc2:: ; 3156 (0:3156) - ret - -; stores hl in [W_TRAINERHEADERPTR] -StoreTrainerHeaderPointer:: ; 3157 (0:3157) - ld a, h - ld [W_TRAINERHEADERPTR], a - ld a, l - ld [W_TRAINERHEADERPTR+1], a - ret - -; executes the current map script from the function pointer array provided in hl. -; a: map script index to execute (unless overridden by [wd733] bit 4) -ExecuteCurMapScriptInTable:: ; 3160 (0:3160) - push af - push de - call StoreTrainerHeaderPointer - pop hl - pop af - push hl - ld hl, W_FLAGS_D733 - bit 4, [hl] - res 4, [hl] - jr z, .useProvidedIndex ; test if map script index was overridden manually - ld a, [W_CURMAPSCRIPT] -.useProvidedIndex - pop hl - ld [W_CURMAPSCRIPT], a - call CallFunctionInTable - ld a, [W_CURMAPSCRIPT] - ret - -LoadGymLeaderAndCityName:: ; 317f (0:317f) - push de - ld de, wGymCityName - ld bc, $11 - call CopyData ; load city name - pop hl - ld de, wGymLeaderName - ld bc, $b - jp CopyData ; load gym leader name - -; reads specific information from trainer header (pointed to at W_TRAINERHEADERPTR) -; a: offset in header data -; 0 -> flag's bit (into wTrainerHeaderFlagBit) -; 2 -> flag's byte ptr (into hl) -; 4 -> before battle text (into hl) -; 6 -> after battle text (into hl) -; 8 -> end battle text (into hl) -ReadTrainerHeaderInfo:: ; 3193 (0:3193) - push de - push af - ld d, $0 - ld e, a - ld hl, W_TRAINERHEADERPTR - ld a, [hli] - ld l, [hl] - ld h, a - add hl, de - pop af - and a - jr nz, .nonZeroOffset - ld a, [hl] - ld [wTrainerHeaderFlagBit], a ; store flag's bit - jr .done -.nonZeroOffset - cp $2 - jr z, .readPointer ; read flag's byte ptr - cp $4 - jr z, .readPointer ; read before battle text - cp $6 - jr z, .readPointer ; read after battle text - cp $8 - jr z, .readPointer ; read end battle text - cp $a - jr nz, .done - ld a, [hli] ; read end battle text (2) but override the result afterwards (XXX why, bug?) - ld d, [hl] - ld e, a - jr .done -.readPointer - ld a, [hli] - ld h, [hl] - ld l, a -.done - pop de - ret - -TrainerFlagAction:: - predef_jump FlagActionPredef - -TalkToTrainer:: ; 31cc (0:31cc) - call StoreTrainerHeaderPointer - xor a - call ReadTrainerHeaderInfo ; read flag's bit - ld a, $2 - call ReadTrainerHeaderInfo ; read flag's byte ptr - ld a, [wTrainerHeaderFlagBit] - ld c, a - ld b, $2 - call TrainerFlagAction ; read trainer's flag - ld a, c - and a - jr z, .trainerNotYetFought ; test trainer's flag - ld a, $6 - call ReadTrainerHeaderInfo ; print after battle text - jp PrintText -.trainerNotYetFought ; 0x31ed - ld a, $4 - call ReadTrainerHeaderInfo ; print before battle text - call PrintText - ld a, $a - call ReadTrainerHeaderInfo ; (?) does nothing apparently (maybe bug in ReadTrainerHeaderInfo) - push de - ld a, $8 - call ReadTrainerHeaderInfo ; read end battle text - pop de - call SaveEndBattleTextPointers - ld hl, W_FLAGS_D733 - set 4, [hl] ; activate map script index override (index is set below) - ld hl, wFlags_0xcd60 - bit 0, [hl] ; test if player is already engaging the trainer (because the trainer saw the player) - ret nz -; if the player talked to the trainer of his own volition - call EngageMapTrainer - ld hl, W_CURMAPSCRIPT - inc [hl] ; increment map script index before StartTrainerBattle increments it again (next script function is usually EndTrainerBattle) - jp StartTrainerBattle - -; checks if any trainers are seeing the player and wanting to fight -CheckFightingMapTrainers:: ; 3219 (0:3219) - call CheckForEngagingTrainers - ld a, [wSpriteIndex] - cp $ff - jr nz, .trainerEngaging - xor a - ld [wSpriteIndex], a - ld [wTrainerHeaderFlagBit], a - ret -.trainerEngaging - ld hl, W_FLAGS_D733 - set 3, [hl] - ld [wcd4f], a - xor a - ld [wcd50], a - predef EmotionBubble - ld a, D_RIGHT | D_LEFT | D_UP | D_DOWN - ld [wJoyIgnore], a - xor a - ldh [$b4], a - call TrainerWalkUpToPlayer_Bank0 - ld hl, W_CURMAPSCRIPT - inc [hl] ; increment map script index (next script function is usually DisplayEnemyTrainerTextAndStartBattle) - ret - -; display the before battle text after the enemy trainer has walked up to the player's sprite -DisplayEnemyTrainerTextAndStartBattle:: ; 324c (0:324c) - ld a, [wd730] - and $1 - ret nz ; return if the enemy trainer hasn't finished walking to the player's sprite - ld [wJoyIgnore], a - ld a, [wSpriteIndex] - ld [hSpriteIndexOrTextID], a - call DisplayTextID - ; fall through - -StartTrainerBattle:: ; 325d (0:325d) - xor a - ld [wJoyIgnore], a - call InitBattleEnemyParameters - ld hl, wd72d - set 6, [hl] - set 7, [hl] - ld hl, wd72e - set 1, [hl] - ld hl, W_CURMAPSCRIPT - inc [hl] ; increment map script index (next script function is usually EndTrainerBattle) - ret - -EndTrainerBattle:: ; 3275 (0:3275) - ld hl, wd126 - set 5, [hl] - set 6, [hl] - ld hl, wd72d - res 7, [hl] - ld hl, wFlags_0xcd60 - res 0, [hl] ; player is no longer engaged by any trainer - ld a, [W_ISINBATTLE] ; W_ISINBATTLE - cp $ff - jp z, ResetButtonPressedAndMapScript - ld a, $2 - call ReadTrainerHeaderInfo - ld a, [wTrainerHeaderFlagBit] - ld c, a - ld b, $1 - call TrainerFlagAction ; flag trainer as fought - ld a, [W_ENEMYMONORTRAINERCLASS] - cp $c8 - jr nc, .skipRemoveSprite ; test if trainer was fought (in that case skip removing the corresponding sprite) - ld hl, W_MISSABLEOBJECTLIST - ld de, $2 - ld a, [wSpriteIndex] - call IsInArray ; search for sprite ID - inc hl - ld a, [hl] - ld [wcc4d], a ; load corresponding missable object index and remove it - predef HideObject -.skipRemoveSprite - ld hl, wd730 - bit 4, [hl] - res 4, [hl] - ret nz - -ResetButtonPressedAndMapScript:: ; 32c1 (0:32c1) - xor a - ld [wJoyIgnore], a - ld [hJoyHeld], a - ld [hJoyPressed], a - ld [hJoyReleased], a - ld [W_CURMAPSCRIPT], a ; reset battle status - ret - -; calls TrainerWalkUpToPlayer -TrainerWalkUpToPlayer_Bank0:: ; 32cf (0:32cf) - ld b, BANK(TrainerWalkUpToPlayer) - ld hl, TrainerWalkUpToPlayer - jp Bankswitch - -; sets opponent type and mon set/lvl based on the engaging trainer data -InitBattleEnemyParameters:: ; 32d7 (0:32d7) - ld a, [wEngagedTrainerClass] - ld [W_CUROPPONENT], a ; wd059 - ld [W_ENEMYMONORTRAINERCLASS], a - cp $c8 - ld a, [wEngagedTrainerSet] ; wcd2e - jr c, .noTrainer - ld [W_TRAINERNO], a ; wd05d - ret -.noTrainer - ld [W_CURENEMYLVL], a ; W_CURENEMYLVL - ret - -GetSpritePosition1:: ; 32ef (0:32ef) - ld hl, _GetSpritePosition1 - jr asm_3301 - -GetSpritePosition2:: ; 32f4 (0:32f4) - ld hl, _GetSpritePosition2 - jr asm_3301 ; 0x32f7 $8 - -SetSpritePosition1:: ; 32f9 (0:32f9) - ld hl, _SetSpritePosition1 - jr asm_3301 - -SetSpritePosition2:: ; 32fe (0:32fe) - ld hl, _SetSpritePosition2 -asm_3301:: ; 3301 (0:3301) - ld b, BANK(_GetSpritePosition1) ; BANK(_GetSpritePosition2), BANK(_SetSpritePosition1), BANK(_SetSpritePosition2) - jp Bankswitch ; indirect jump to one of the four functions - -CheckForEngagingTrainers:: ; 3306 (0:3306) - xor a - call ReadTrainerHeaderInfo ; read trainer flag's bit (unused) - ld d, h ; store trainer header address in de - ld e, l -.trainerLoop - call StoreTrainerHeaderPointer ; set trainer header pointer to current trainer - ld a, [de] - ld [wSpriteIndex], a ; store trainer flag's bit - ld [wTrainerHeaderFlagBit], a - cp $ff - ret z - ld a, $2 - call ReadTrainerHeaderInfo ; read trainer flag's byte ptr - ld b, $2 - ld a, [wTrainerHeaderFlagBit] - ld c, a - call TrainerFlagAction ; read trainer flag - ld a, c - and a - jr nz, .trainerAlreadyFought - push hl - push de - push hl - xor a - call ReadTrainerHeaderInfo ; get trainer header pointer - inc hl - ld a, [hl] ; read trainer engage distance - pop hl - ld [wTrainerEngageDistance], a - ld a, [wSpriteIndex] - swap a - ld [wTrainerSpriteOffset], a ; wWhichTrade - predef TrainerEngage - pop de - pop hl - ld a, [wTrainerSpriteOffset] ; wWhichTrade - and a - ret nz ; break if the trainer is engaging -.trainerAlreadyFought - ld hl, $c - add hl, de - ld d, h - ld e, l - jr .trainerLoop - -; hl = text if the player wins -; de = text if the player loses -SaveEndBattleTextPointers:: ; 3354 (0:3354) - ld a, [H_LOADEDROMBANK] - ld [wEndBattleTextRomBank], a - ld a, h - ld [wEndBattleWinTextPointer], a - ld a, l - ld [wEndBattleWinTextPointer + 1], a - ld a, d - ld [wEndBattleLoseTextPointer], a - ld a, e - ld [wEndBattleLoseTextPointer + 1], a - ret - -; loads data of some trainer on the current map and plays pre-battle music -; [wSpriteIndex]: sprite ID of trainer who is engaged -EngageMapTrainer:: ; 336a (0:336a) - ld hl, W_MAPSPRITEEXTRADATA - ld d, $0 - ld a, [wSpriteIndex] - dec a - add a - ld e, a - add hl, de ; seek to engaged trainer data - ld a, [hli] ; load trainer class - ld [wEngagedTrainerClass], a - ld a, [hl] ; load trainer mon set - ld [wEnemyMonAttackMod], a ; wcd2e - jp PlayTrainerMusic - -PrintEndBattleText:: ; 3381 (0:3381) - push hl - ld hl, wd72d - bit 7, [hl] - res 7, [hl] - pop hl - ret z - ld a, [H_LOADEDROMBANK] - push af - ld a, [wEndBattleTextRomBank] - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a - push hl - callba SaveTrainerName - ld hl, TrainerEndBattleText - call PrintText - pop hl - pop af - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a - callba FreezeEnemyTrainerSprite - jp WaitForSoundToFinish - -GetSavedEndBattleTextPointer:: ; 33b7 (0:33b7) - ld a, [wBattleResult] - and a -; won battle - jr nz, .lostBattle - ld a, [wEndBattleWinTextPointer] - ld h, a - ld a, [wEndBattleWinTextPointer + 1] - ld l, a - ret -.lostBattle - ld a, [wEndBattleLoseTextPointer] - ld h, a - ld a, [wEndBattleLoseTextPointer + 1] - ld l, a - ret - -TrainerEndBattleText:: ; 33cf (0:33cf) - TX_FAR _TrainerNameText - db $08 - call GetSavedEndBattleTextPointer - call TextCommandProcessor - jp TextScriptEnd - -; XXX unused? -Func_33dd:: ; 33dd (0:33dd) - ld a, [wFlags_0xcd60] - bit 0, a - ret nz - call EngageMapTrainer - xor a - ret - -PlayTrainerMusic:: ; 33e8 (0:33e8) - ld a, [wEngagedTrainerClass] - cp $c8 + SONY1 - ret z - cp $c8 + SONY2 - ret z - cp $c8 + SONY3 - ret z - ld a, [W_GYMLEADERNO] ; W_GYMLEADERNO - and a - ret nz - xor a - ld [wMusicHeaderPointer], a - ld a, $ff - call PlaySound ; stop music - ld a, BANK(Music_MeetEvilTrainer) - ld [wc0ef], a - ld [wc0f0], a - ld a, [wEngagedTrainerClass] - ld b, a - ld hl, EvilTrainerList -.evilTrainerListLoop - ld a, [hli] - cp $ff - jr z, .noEvilTrainer - cp b - jr nz, .evilTrainerListLoop - ld a, MUSIC_MEET_EVIL_TRAINER - jr .PlaySound -.noEvilTrainer - ld hl, FemaleTrainerList -.femaleTrainerListLoop - ld a, [hli] - cp $ff - jr z, .maleTrainer - cp b - jr nz, .femaleTrainerListLoop - ld a, MUSIC_MEET_FEMALE_TRAINER - jr .PlaySound -.maleTrainer - ld a, MUSIC_MEET_MALE_TRAINER -.PlaySound - ld [wc0ee], a - jp PlaySound - -INCLUDE "data/trainer_types.asm" - -; checks if the player's coordinates match an arrow movement tile's coordinates -; and if so, decodes the RLE movement data -; b = player Y -; c = player X -DecodeArrowMovementRLE:: ; 3442 (0:3442) - ld a, [hli] - cp $ff - ret z ; no match in the list - cp b - jr nz, .nextArrowMovementTileEntry1 - ld a, [hli] - cp c - jr nz, .nextArrowMovementTileEntry2 - ld a, [hli] - ld d, [hl] - ld e, a - ld hl, wSimulatedJoypadStatesEnd - call DecodeRLEList - dec a - ld [wSimulatedJoypadStatesIndex], a - ret -.nextArrowMovementTileEntry1 - inc hl -.nextArrowMovementTileEntry2 - inc hl - inc hl - jr DecodeArrowMovementRLE - -FuncTX_ItemStoragePC:: ; 3460 (0:3460) - call SaveScreenTilesToBuffer2 - ld b, BANK(PlayerPC) - ld hl, PlayerPC - jr bankswitchAndContinue - -FuncTX_BillsPC:: ; 346a (0:346a) - call SaveScreenTilesToBuffer2 - ld b, BANK(BillsPC_) - ld hl, BillsPC_ - jr bankswitchAndContinue - -FuncTX_SlotMachine:: ; 3474 (0:3474) -; XXX find a better name for this function -; special_F7 - ld b,BANK(CeladonPrizeMenu) - ld hl,CeladonPrizeMenu -bankswitchAndContinue:: ; 3479 (0:3479) - call Bankswitch - jp HoldTextDisplayOpen ; continue to main text-engine function - -FuncTX_PokemonCenterPC:: ; 347f (0:347f) - ld b, BANK(ActivatePC) - ld hl, ActivatePC - jr bankswitchAndContinue - -StartSimulatingJoypadStates:: ; 3486 (0:3486) - xor a - ld [wOverrideSimulatedJoypadStatesMask], a - ld [wSpriteStateData2 + $06], a ; player's sprite movement byte 1 - ld hl, wd730 - set 7, [hl] - ret - -IsItemInBag:: ; 3493 (0:3493) -; given an item_id in b -; set zero flag if item isn't in player's bag -; else reset zero flag -; related to Pokémon Tower and ghosts - predef IsItemInBag_ - ld a,b - and a - ret - -DisplayPokedex:: ; 349b (0:349b) - ld [wd11e], a - ld b, BANK(Func_7c18) - ld hl, Func_7c18 - jp Bankswitch - -SetSpriteFacingDirectionAndDelay:: ; 34a6 (0:34a6) - call SetSpriteFacingDirection - ld c, $6 - jp DelayFrames - -SetSpriteFacingDirection:: ; 34ae (0:34ae) - ld a, $9 - ld [H_SPRITEDATAOFFSET], a - call GetPointerWithinSpriteStateData1 - ld a, [$ff8d] - ld [hl], a - ret - -SetSpriteImageIndexAfterSettingFacingDirection:: ; 34b9 (0:34b9) - ld de, -7 - add hl, de - ld [hl], a - ret - -; tests if the player's coordinates are in a specified array -; INPUT: -; hl = address of array -; OUTPUT: -; [wWhichTrade] = if there is match, the matching array index -; sets carry if the coordinates are in the array, clears carry if not -ArePlayerCoordsInArray:: ; 34bf (0:34bf) - ld a,[W_YCOORD] - ld b,a - ld a,[W_XCOORD] - ld c,a - ; fallthrough - -CheckCoords:: ; 34c7 (0:34c7) - xor a - ld [wWhichTrade],a -.loop - ld a,[hli] - cp a,$ff ; reached terminator? - jr z,.notInArray - push hl - ld hl,wWhichTrade - inc [hl] - pop hl -.compareYCoord - cp b - jr z,.compareXCoord - inc hl - jr .loop -.compareXCoord - ld a,[hli] - cp c - jr nz,.loop -.inArray - scf - ret -.notInArray - and a - ret - -; tests if a boulder's coordinates are in a specified array -; INPUT: -; hl = address of array -; [H_SPRITEINDEX] = index of boulder sprite -; OUTPUT: -; [wWhichTrade] = if there is match, the matching array index -; sets carry if the coordinates are in the array, clears carry if not -CheckBoulderCoords:: ; 34e4 (0:34e4) - push hl - ld hl, wSpriteStateData2 + $04 - ld a, [H_SPRITEINDEX] - swap a - ld d, $0 - ld e, a - add hl, de - ld a, [hli] - sub $4 ; because sprite coordinates are offset by 4 - ld b, a - ld a, [hl] - sub $4 ; because sprite coordinates are offset by 4 - ld c, a - pop hl - jp CheckCoords - -GetPointerWithinSpriteStateData1:: ; 34fc (0:34fc) - ld h, $c1 - jr _GetPointerWithinSpriteStateData - -GetPointerWithinSpriteStateData2:: ; 3500 (0:3500) - ld h, $c2 - -_GetPointerWithinSpriteStateData: - ld a, [H_SPRITEDATAOFFSET] - ld b, a - ld a, [H_SPRITEINDEX] - swap a - add b - ld l, a - ret - -; decodes a $ff-terminated RLEncoded list -; each entry is a pair of bytes <byte value> <repetitions> -; the final $ff will be replicated in the output list and a contains the number of bytes written -; de: input list -; hl: output list -DecodeRLEList:: ; 350c (0:350c) - xor a - ld [wRLEByteCount], a ; count written bytes here -.listLoop - ld a, [de] - cp $ff - jr z, .endOfList - ld [H_DOWNARROWBLINKCNT1], a ; store byte value to be written - inc de - ld a, [de] - ld b, $0 - ld c, a ; number of bytes to be written - ld a, [wRLEByteCount] - add c - ld [wRLEByteCount], a ; update total number of written bytes - ld a, [H_DOWNARROWBLINKCNT1] ; $ff8b - call FillMemory ; write a c-times to output - inc de - jr .listLoop -.endOfList - ld a, $ff - ld [hl], a ; write final $ff - ld a, [wRLEByteCount] - inc a ; include sentinel in counting - ret - -; sets movement byte 1 for sprite [$FF8C] to $FE and byte 2 to [$FF8D] -SetSpriteMovementBytesToFE:: ; 3533 (0:3533) - push hl - call GetSpriteMovementByte1Pointer - ld [hl], $fe - call GetSpriteMovementByte2Pointer - ld a, [$ff8d] - ld [hl], a - pop hl - ret - -; sets both movement bytes for sprite [$FF8C] to $FF -SetSpriteMovementBytesToFF:: ; 3541 (0:3541) - push hl - call GetSpriteMovementByte1Pointer - ld [hl],$FF - call GetSpriteMovementByte2Pointer - ld [hl],$FF ; prevent person from walking? - pop hl - ret - -; returns the sprite movement byte 1 pointer for sprite [$FF8C] in hl -GetSpriteMovementByte1Pointer:: ; 354e (0:354e) - ld h,$C2 - ld a,[H_SPRITEINDEX] ; the sprite to move - swap a - add a,6 - ld l,a - ret - -; returns the sprite movement byte 2 pointer for sprite [$FF8C] in hl -GetSpriteMovementByte2Pointer:: ; 3558 (0:3558) - push de - ld hl,W_MAPSPRITEDATA - ld a,[$FF8C] ; the sprite to move - dec a - add a - ld d,0 - ld e,a - add hl,de - pop de - ret - -GetTrainerInformation:: ; 3566 (0:3566) - call GetTrainerName - ld a, [wLinkState] - and a - jr nz, .linkBattle - ld a, Bank(TrainerPicAndMoneyPointers) - call BankswitchHome - ld a, [W_TRAINERCLASS] ; wd031 - dec a - ld hl, TrainerPicAndMoneyPointers - ld bc, $5 - call AddNTimes - ld de, wTrainerPicPointer - ld a, [hli] - ld [de], a - inc de - ld a, [hli] - ld [de], a - ld de, wd046 - ld a, [hli] - ld [de], a - inc de - ld a, [hli] - ld [de], a - jp BankswitchBack -.linkBattle - ld hl, wTrainerPicPointer - ld de, RedPicFront - ld [hl], e - inc hl - ld [hl], d - ret - -GetTrainerName:: ; 359e (0:359e) - ld b, BANK(GetTrainerName_) - ld hl, GetTrainerName_ - jp Bankswitch - - -HasEnoughMoney:: -; Check if the player has at least as much -; money as the 3-byte BCD value at $ff9f. - ld de, wPlayerMoney - ld hl, $ff9f - ld c, 3 - jp StringCmp - -HasEnoughCoins:: -; Check if the player has at least as many -; coins as the 2-byte BCD value at $ffa0. - ld de, wPlayerCoins - ld hl, $ffa0 - ld c, 2 - jp StringCmp - - -BankswitchHome:: ; 35d9 (0:35d9) -; switches to bank # in a -; Only use this when in the home bank! - ld [wcf09],a - ld a,[H_LOADEDROMBANK] - ld [wcf08],a - ld a,[wcf09] - call BankswitchCommon - ret - -BankswitchBack:: ; 35e8 (0:35e8) -; returns from BankswitchHome - ld a,[wcf08] - call BankswitchCommon - ret - -BankswitchCommon:: ; 3e7e (0:3e7e) - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -Bankswitch:: ; 3e84 (0:3e84) -; self-contained bankswitch, use this when not in the home bank -; switches to the bank in b - ld a,[H_LOADEDROMBANK] - push af - ld a,b - ld [H_LOADEDROMBANK],a - ld [$2000],a - call .jumptoaddress - pop bc - ld a,b - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret -.jumptoaddress - jp [hl] - -; displays yes/no choice -; yes -> set carry -YesNoChoice:: ; 35ec (0:35ec) - call SaveScreenTilesToBuffer1 - call InitYesNoTextBoxParameters - jr DisplayYesNoChoice - -Func_35f4:: ; 35f4 (0:35f4) - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call InitYesNoTextBoxParameters - jp DisplayTextBoxID - -InitYesNoTextBoxParameters:: ; 35ff (0:35ff) - xor a ; YES_NO_MENU - ld [wTwoOptionMenuID], a - hlCoord 14, 7 - ld bc, $80f - ret - -YesNoChoicePokeCenter:: ; 360a (0:360a) - call SaveScreenTilesToBuffer1 - ld a, HEAL_CANCEL_MENU - ld [wTwoOptionMenuID], a - hlCoord 11, 6 - ld bc, $80c - jr DisplayYesNoChoice - -Func_361a:: ; 361a (0:361a) - call SaveScreenTilesToBuffer1 - ld a, WIDE_YES_NO_MENU - ld [wTwoOptionMenuID], a - hlCoord 12, 7 - ld bc, $080d -DisplayYesNoChoice:: ; 3628 (0:3628) - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID - jp LoadScreenTilesFromBuffer1 - -; calculates the difference |a-b|, setting carry flag if a<b -CalcDifference:: ; 3633 (0:3633) - sub b - ret nc - cpl - add $1 - scf - ret - -MoveSprite:: ; 363a (0:363a) -; move the sprite [$FF8C] with the movement pointed to by de -; actually only copies the movement data to wcc5b for later - call SetSpriteMovementBytesToFF -MoveSprite_:: ; 363d (0:363d) - push hl - push bc - call GetSpriteMovementByte1Pointer - xor a - ld [hl],a - ld hl,wcc5b - ld c,0 - -.loop - ld a,[de] - ld [hli],a - inc de - inc c - cp a,$FF ; have we reached the end of the movement data? - jr nz,.loop - - ld a,c - ld [wcf0f],a ; number of steps taken - - pop bc - ld hl,wd730 - set 0,[hl] - pop hl - xor a - ld [wOverrideSimulatedJoypadStatesMask],a - ld [wSimulatedJoypadStatesEnd],a - dec a - ld [wJoyIgnore],a - ld [wWastedByteCD3A],a - ret - -; divides [$ffe5] by [$ffe6] and stores the quotient in [$ffe7] -DivideBytes:: ; 366b (0:366b) - push hl - ld hl, $ffe7 - xor a - ld [hld], a - ld a, [hld] - and a - jr z, .done - ld a, [hli] -.loop - sub [hl] - jr c, .done - inc hl - inc [hl] - dec hl - jr .loop -.done - pop hl - ret - - -LoadFontTilePatterns:: - ld a, [rLCDC] - bit 7, a ; is the LCD enabled? - jr nz, .on -.off - ld hl, FontGraphics - ld de, vFont - ld bc, $400 - ld a, BANK(FontGraphics) - jp FarCopyDataDouble ; if LCD is off, transfer all at once -.on - ld de, FontGraphics - ld hl, vFont - ld bc, BANK(FontGraphics) << 8 | $80 - jp CopyVideoDataDouble ; if LCD is on, transfer during V-blank - -LoadTextBoxTilePatterns:: - ld a, [rLCDC] - bit 7, a ; is the LCD enabled? - jr nz, .on -.off - ld hl, TextBoxGraphics - ld de, vChars2 + $600 - ld bc, $200 - ld a, BANK(TextBoxGraphics) - jp FarCopyData2 ; if LCD is off, transfer all at once -.on - ld de, TextBoxGraphics - ld hl, vChars2 + $600 - ld bc, BANK(TextBoxGraphics) << 8 | $20 - jp CopyVideoData ; if LCD is on, transfer during V-blank - -LoadHpBarAndStatusTilePatterns:: - ld a, [rLCDC] - bit 7, a ; is the LCD enabled? - jr nz, .on -.off - ld hl, HpBarAndStatusGraphics - ld de, vChars2 + $620 - ld bc, $1e0 - ld a, BANK(HpBarAndStatusGraphics) - jp FarCopyData2 ; if LCD is off, transfer all at once -.on - ld de, HpBarAndStatusGraphics - ld hl, vChars2 + $620 - ld bc, BANK(HpBarAndStatusGraphics) << 8 | $1e - jp CopyVideoData ; if LCD is on, transfer during V-blank - - -UncompressSpriteFromDE:: ; 36eb (0:36eb) -; Decompress pic at a:de. - ld hl, W_SPRITEINPUTPTR - ld [hl], e - inc hl - ld [hl], d - jp UncompressSpriteData - - -SaveScreenTilesToBuffer2:: ; 36f4 (0:36f4) - ld hl, wTileMap - ld de, wTileMapBackup2 - ld bc, $168 - call CopyData - ret - -LoadScreenTilesFromBuffer2:: ; 3701 (0:3701) - call LoadScreenTilesFromBuffer2DisableBGTransfer - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a ; $ffba - ret - -; loads screen tiles stored in wTileMapBackup2 but leaves H_AUTOBGTRANSFERENABLED disabled -LoadScreenTilesFromBuffer2DisableBGTransfer:: ; 3709 (0:3709) - xor a - ld [H_AUTOBGTRANSFERENABLED], a ; $ffba - ld hl, wTileMapBackup2 - ld de, wTileMap - ld bc, $168 - call CopyData - ret - -SaveScreenTilesToBuffer1:: ; 3719 (0:3719) - ld hl, wTileMap - ld de, wTileMapBackup - ld bc, $168 - jp CopyData - -LoadScreenTilesFromBuffer1:: ; 3725 (0:3725) - xor a - ld [H_AUTOBGTRANSFERENABLED], a ; $ffba - ld hl, wTileMapBackup - ld de, wTileMap - ld bc, $168 - call CopyData - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a ; $ffba - ret - -DelayFrames:: ; 3739 (0:3739) -; wait n frames, where n is the value in c - call DelayFrame - dec c - jr nz,DelayFrames - ret - -PlaySoundWaitForCurrent:: ; 3740 (0:3740) - push af - call WaitForSoundToFinish - pop af - jp PlaySound - -; Wait for sound to finish playing -WaitForSoundToFinish:: ; 3748 (0:3748) - ld a, [wLowHealthAlarm] - and $80 - ret nz - push hl -.asm_374f - ld hl, wc02a - xor a - or [hl] - inc hl - or [hl] - inc hl - inc hl - or [hl] - jr nz, .asm_374f - pop hl - ret - -NamePointers:: ; 375d (0:375d) - dw MonsterNames - dw MoveNames - dw UnusedNames - dw ItemNames - dw wPartyMonOT ; player's OT names list - dw wEnemyMonOT ; enemy's OT names list - dw TrainerNames - -GetName:: ; 376b (0:376b) -; arguments: -; [wd0b5] = which name -; [wNameListType] = which list -; [wPredefBank] = bank of list -; -; returns pointer to name in de - ld a,[wd0b5] - ld [wd11e],a - - ; TM names are separate from item names. - ; BUG: This applies to all names instead of just items. - cp HM_01 - jp nc, GetMachineName - - ld a,[H_LOADEDROMBANK] - push af - push hl - push bc - push de - ld a,[wNameListType] ;List3759_entrySelector - dec a - jr nz,.otherEntries - ;1 = MON_NAMES - call GetMonName - ld hl,11 - add hl,de - ld e,l - ld d,h - jr .gotPtr -.otherEntries ; $378d - ;2-7 = OTHER ENTRIES - ld a,[wPredefBank] - ld [H_LOADEDROMBANK],a - ld [$2000],a - ld a,[wNameListType] ;VariousNames' entryID - dec a - add a - ld d,0 - ld e,a - jr nc,.skip - inc d -.skip ; $37a0 - ld hl,NamePointers - add hl,de - ld a,[hli] - ld [$ff96],a - ld a,[hl] - ld [$ff95],a - ld a,[$ff95] - ld h,a - ld a,[$ff96] - ld l,a - ld a,[wd0b5] - ld b,a - ld c,0 -.nextName - ld d,h - ld e,l -.nextChar - ld a,[hli] - cp a, "@" - jr nz,.nextChar - inc c ;entry counter - ld a,b ;wanted entry - cp c - jr nz,.nextName - ld h,d - ld l,e - ld de,wcd6d - ld bc,$0014 - call CopyData -.gotPtr ; $37cd - ld a,e - ld [wcf8d],a - ld a,d - ld [wcf8e],a - pop de - pop bc - pop hl - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -GetItemPrice:: ; 37df (0:37df) -; Stores item's price as BCD at hItemPrice (3 bytes) -; Input: [wcf91] = item id - ld a, [H_LOADEDROMBANK] - push af - ld a, [wListMenuID] - cp MOVESLISTMENU - ld a, BANK(ItemPrices) - jr nz, .asm_37ed - ld a, $f ; hardcoded Bank -.asm_37ed - ld [H_LOADEDROMBANK], a - ld [$2000], a - ld hl, wItemPrices - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [wcf91] ; a contains item id - cp HM_01 - jr nc, .getTMPrice - ld bc, $3 -.asm_3802 - add hl, bc - dec a - jr nz, .asm_3802 - dec hl - ld a, [hld] - ld [hItemPrice + 2], a - ld a, [hld] - ld [hItemPrice + 1], a - ld a, [hl] - ld [hItemPrice], a - jr .asm_381c -.getTMPrice - ld a, Bank(GetMachinePrice) - ld [H_LOADEDROMBANK], a - ld [$2000], a - call GetMachinePrice -.asm_381c - ld de, hItemPrice - pop af - ld [H_LOADEDROMBANK], a - ld [$2000], a - ret - -; copies a string from [de] to [wcf4b] -CopyStringToCF4B:: ; 3826 (0:3826) - ld hl, wcf4b - ; fall through - -; copies a string from [de] to [hl] -CopyString:: ; 3829 (0:3829) - ld a, [de] - inc de - ld [hli], a - cp "@" - jr nz, CopyString - ret - -; this function is used when lower button sensitivity is wanted (e.g. menus) -; OUTPUT: [hJoy5] = pressed buttons in usual format -; there are two flags that control its functionality, [hJoy6] and [hJoy7] -; there are esentially three modes of operation -; 1. Get newly pressed buttons only -; ([hJoy7] == 0, [hJoy6] == any) -; Just copies [hJoyPressed] to [hJoy5]. -; 2. Get currently pressed buttons at low sample rate with delay -; ([hJoy7] == 1, [hJoy6] != 0) -; If the user holds down buttons for more than half a second, -; report buttons as being pressed up to 12 times per second thereafter. -; If the user holds down buttons for less than half a second, -; report only one button press. -; 3. Same as 2, but report no buttons as pressed if A or B is held down. -; ([hJoy7] == 1, [hJoy6] == 0) -JoypadLowSensitivity:: ; 3831 (0:3831) - call Joypad - ld a,[hJoy7] ; flag - and a ; get all currently pressed buttons or only newly pressed buttons? - ld a,[hJoyPressed] ; newly pressed buttons - jr z,.storeButtonState - ld a,[hJoyHeld] ; all currently pressed buttons -.storeButtonState - ld [hJoy5],a - ld a,[hJoyPressed] ; newly pressed buttons - and a ; have any buttons been newly pressed since last check? - jr z,.noNewlyPressedButtons -.newlyPressedButtons - ld a,30 ; half a second delay - ld [H_FRAMECOUNTER],a - ret -.noNewlyPressedButtons - ld a,[H_FRAMECOUNTER] - and a ; is the delay over? - jr z,.delayOver -.delayNotOver - xor a - ld [hJoy5],a ; report no buttons as pressed - ret -.delayOver -; if [hJoy6] = 0 and A or B is pressed, report no buttons as pressed - ld a,[hJoyHeld] - and A_BUTTON | B_BUTTON - jr z,.setShortDelay - ld a,[hJoy6] ; flag - and a - jr nz,.setShortDelay - xor a - ld [hJoy5],a -.setShortDelay - ld a,5 ; 1/12 of a second delay - ld [H_FRAMECOUNTER],a - ret - -WaitForTextScrollButtonPress:: ; 3865 (0:3865) - ld a, [H_DOWNARROWBLINKCNT1] - push af - ld a, [H_DOWNARROWBLINKCNT2] - push af - xor a - ld [H_DOWNARROWBLINKCNT1], a - ld a, $6 - ld [H_DOWNARROWBLINKCNT2], a -.loop - push hl - ld a, [wTownMapSpriteBlinkingEnabled] - and a - jr z, .skipAnimation - call TownMapSpriteBlinkingAnimation -.skipAnimation - hlCoord 18, 16 - call HandleDownArrowBlinkTiming - pop hl - call JoypadLowSensitivity - predef CableClub_Run - ld a, [hJoy5] - and A_BUTTON | B_BUTTON - jr z, .loop - pop af - ld [H_DOWNARROWBLINKCNT2], a - pop af - ld [H_DOWNARROWBLINKCNT1], a - ret - -; (unless in link battle) waits for A or B being pressed and outputs the scrolling sound effect -ManualTextScroll:: ; 3898 (0:3898) - ld a, [wLinkState] - cp LINK_STATE_BATTLING - jr z, .inLinkBattle - call WaitForTextScrollButtonPress - ld a, (SFX_02_40 - SFX_Headers_02) / 3 - jp PlaySound -.inLinkBattle - ld c, $41 - jp DelayFrames - -; function to do multiplication -; all values are big endian -; INPUT -; FF96-FF98 = multiplicand -; FF99 = multiplier -; OUTPUT -; FF95-FF98 = product -Multiply:: ; 38ac (0:38ac) - push hl - push bc - callab _Multiply - pop bc - pop hl - ret - -; function to do division -; all values are big endian -; INPUT -; FF95-FF98 = dividend -; FF99 = divisor -; b = number of bytes in the dividend (starting from FF95) -; OUTPUT -; FF95-FF98 = quotient -; FF99 = remainder -Divide:: ; 38b9 (0:38b9) - push hl - push de - push bc - ld a,[H_LOADEDROMBANK] - push af - ld a,Bank(_Divide) - ld [H_LOADEDROMBANK],a - ld [$2000],a - call _Divide - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - pop bc - pop de - pop hl - ret - -; This function is used to wait a short period after printing a letter to the -; screen unless the player presses the A/B button or the delay is turned off -; through the [wd730] or [wd358] flags. -PrintLetterDelay:: ; 38d3 (0:38d3) - ld a,[wd730] - bit 6,a - ret nz - ld a,[wd358] - bit 1,a - ret z - push hl - push de - push bc - ld a,[wd358] - bit 0,a - jr z,.waitOneFrame - ld a,[W_OPTIONS] - and $f - ld [H_FRAMECOUNTER],a - jr .checkButtons -.waitOneFrame - ld a,1 - ld [H_FRAMECOUNTER],a -.checkButtons - call Joypad - ld a,[hJoyHeld] -.checkAButton - bit 0,a ; is the A button pressed? - jr z,.checkBButton - jr .endWait -.checkBButton - bit 1,a ; is the B button pressed? - jr z,.buttonsNotPressed -.endWait - call DelayFrame - jr .done -.buttonsNotPressed ; if neither A nor B is pressed - ld a,[H_FRAMECOUNTER] - and a - jr nz,.checkButtons -.done - pop bc - pop de - pop hl - ret - -; Copies [hl, bc) to [de, bc - hl). -; In other words, the source data is from hl up to but not including bc, -; and the destination is de. -CopyDataUntil:: ; 3913 (0:3913) - ld a,[hli] - ld [de],a - inc de - ld a,h - cp b - jr nz,CopyDataUntil - ld a,l - cp c - jr nz,CopyDataUntil - ret - -; Function to remove a pokemon from the party or the current box. -; wWhichPokemon determines the pokemon. -; [wcf95] == 0 specifies the party. -; [wcf95] != 0 specifies the current box. -RemovePokemon:: ; 391f (0:391f) - ld hl, _RemovePokemon - ld b, BANK(_RemovePokemon) - jp Bankswitch - -AddPartyMon:: ; 3927 (0:3927) - push hl - push de - push bc - callba _AddPartyMon - pop bc - pop de - pop hl - ret - -; calculates all 5 stats of current mon and writes them to [de] -CalcStats:: ; 3936 (0:3936) - ld c, $0 -.statsLoop - inc c - call CalcStat - ld a, [H_MULTIPLICAND+1] - ld [de], a - inc de - ld a, [H_MULTIPLICAND+2] - ld [de], a - inc de - ld a, c - cp $5 - jr nz, .statsLoop - ret - -; calculates stat c of current mon -; c: stat to calc (HP=1,Atk=2,Def=3,Spd=4,Spc=5) -; b: consider stat exp? -; hl: base ptr to stat exp values ([hl + 2*c - 1] and [hl + 2*c]) -CalcStat:: ; 394a (0:394a) - push hl - push de - push bc - ld a, b - ld d, a - push hl - ld hl, W_MONHEADER - ld b, $0 - add hl, bc - ld a, [hl] ; read base value of stat - ld e, a - pop hl - push hl - sla c - ld a, d - and a - jr z, .statExpDone ; consider stat exp? - add hl, bc ; skip to corresponding stat exp value -.statExpLoop ; calculates ceil(Sqrt(stat exp)) in b - xor a - ld [H_MULTIPLICAND], a - ld [H_MULTIPLICAND+1], a - inc b ; increment current stat exp bonus - ld a, b - cp $ff - jr z, .statExpDone - ld [H_MULTIPLICAND+2], a - ld [H_MULTIPLIER], a - call Multiply - ld a, [hld] - ld d, a - ld a, [$ff98] - sub d - ld a, [hli] - ld d, a - ld a, [$ff97] - sbc d ; test if (current stat exp bonus)^2 < stat exp - jr c, .statExpLoop -.statExpDone - srl c - pop hl - push bc - ld bc, $b ; skip to stat IV values - add hl, bc - pop bc - ld a, c - cp $2 - jr z, .getAttackIV - cp $3 - jr z, .getDefenseIV - cp $4 - jr z, .getSpeedIV - cp $5 - jr z, .getSpecialIV -.getHpIV - push bc - ld a, [hl] ; Atk IV - swap a - and $1 - sla a - sla a - sla a - ld b, a - ld a, [hli] ; Def IV - and $1 - sla a - sla a - add b - ld b, a - ld a, [hl] ; Spd IV - swap a - and $1 - sla a - add b - ld b, a - ld a, [hl] ; Spc IV - and $1 - add b ; HP IV: LSB of the other 4 IVs - pop bc - jr .calcStatFromIV -.getAttackIV - ld a, [hl] - swap a - and $f - jr .calcStatFromIV -.getDefenseIV - ld a, [hl] - and $f - jr .calcStatFromIV -.getSpeedIV - inc hl - ld a, [hl] - swap a - and $f - jr .calcStatFromIV -.getSpecialIV - inc hl - ld a, [hl] - and $f -.calcStatFromIV - ld d, $0 - add e - ld e, a - jr nc, .noCarry - inc d ; de = Base + IV -.noCarry - sla e - rl d ; de = (Base + IV) * 2 - srl b - srl b ; b = ceil(Sqrt(stat exp)) / 4 - ld a, b - add e - jr nc, .noCarry2 - inc d ; da = (Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4 -.noCarry2 - ld [H_MULTIPLICAND+2], a - ld a, d - ld [H_MULTIPLICAND+1], a - xor a - ld [H_MULTIPLICAND], a - ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL - ld [H_MULTIPLIER], a - call Multiply ; ((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level - ld a, [H_MULTIPLICAND] - ld [H_DIVIDEND], a - ld a, [H_MULTIPLICAND+1] - ld [H_DIVIDEND+1], a - ld a, [H_MULTIPLICAND+2] - ld [H_DIVIDEND+2], a - ld a, $64 - ld [H_DIVISOR], a - ld a, $3 - ld b, a - call Divide ; (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 - ld a, c - cp $1 - ld a, $5 - jr nz, .notHPStat - ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL - ld b, a - ld a, [H_MULTIPLICAND+2] - add b - ld [H_MULTIPLICAND+2], a - jr nc, .noCarry3 - ld a, [H_MULTIPLICAND+1] - inc a - ld [H_MULTIPLICAND+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level -.noCarry3 - ld a, $a -.notHPStat - ld b, a - ld a, [H_MULTIPLICAND+2] - add b - ld [H_MULTIPLICAND+2], a - jr nc, .noCarry4 - ld a, [H_MULTIPLICAND+1] - inc a ; non-HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + 5 - ld [H_MULTIPLICAND+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level + 10 -.noCarry4 - ld a, [H_MULTIPLICAND+1] ; check for overflow (>999) - cp $4 - jr nc, .overflow - cp $3 - jr c, .noOverflow - ld a, [H_MULTIPLICAND+2] - cp $e8 - jr c, .noOverflow -.overflow - ld a, $3 ; overflow: cap at 999 - ld [H_MULTIPLICAND+1], a - ld a, $e7 - ld [H_MULTIPLICAND+2], a -.noOverflow - pop bc - pop de - pop hl - ret - -AddEnemyMonToPlayerParty:: ; 3a53 (0:3a53) - ld a, [H_LOADEDROMBANK] - push af - ld a, BANK(_AddEnemyMonToPlayerParty) - ld [H_LOADEDROMBANK], a - ld [$2000], a - call _AddEnemyMonToPlayerParty - pop bc - ld a, b - ld [H_LOADEDROMBANK], a - ld [$2000], a - ret - -Func_3a68:: ; 3a68 (0:3a68) - ld a, [H_LOADEDROMBANK] - push af - ld a, BANK(Func_f51e) - ld [H_LOADEDROMBANK], a - ld [$2000], a - call Func_f51e - pop bc - ld a, b - ld [H_LOADEDROMBANK], a - ld [$2000], a - ret - -; skips a text entries, each of size $b (like trainer name, OT name, rival name, ...) -; hl: base pointer, will be incremented by $b * a -SkipFixedLengthTextEntries:: ; 3a7d (0:3a7d) - and a - ret z - ld bc, $b -.skipLoop - add hl, bc - dec a - jr nz, .skipLoop - ret - -AddNTimes:: ; 3a87 (0:3a87) -; add bc to hl a times - and a - ret z -.loop - add hl,bc - dec a - jr nz,.loop - ret - -; Compare strings, c bytes in length, at de and hl. -; Often used to compare big endian numbers in battle calculations. -StringCmp:: ; 3a8e (0:3a8e) - ld a,[de] - cp [hl] - ret nz - inc de - inc hl - dec c - jr nz,StringCmp - ret - -; INPUT: -; a = oam block index (each block is 4 oam entries) -; b = Y coordinate of upper left corner of sprite -; c = X coordinate of upper left corner of sprite -; de = base address of 4 tile number and attribute pairs -WriteOAMBlock:: ; 3a97 (0:3a97) - ld h,wOAMBuffer / $100 - swap a ; multiply by 16 - ld l,a - call .writeOneEntry ; upper left - push bc - ld a,8 - add c - ld c,a - call .writeOneEntry ; upper right - pop bc - ld a,8 - add b - ld b,a - call .writeOneEntry ; lower left - ld a,8 - add c - ld c,a - ; lower right -.writeOneEntry - ld [hl],b ; Y coordinate - inc hl - ld [hl],c ; X coordinate - inc hl - ld a,[de] ; tile number - inc de - ld [hli],a - ld a,[de] ; attribute - inc de - ld [hli],a - ret - -HandleMenuInput:: ; 3abe (0:3abe) - xor a - ld [wd09b],a - -HandleMenuInputPokemonSelection:: ; 3ac2 (0:3ac2) - ld a,[H_DOWNARROWBLINKCNT1] - push af - ld a,[H_DOWNARROWBLINKCNT2] - push af ; save existing values on stack - xor a - ld [H_DOWNARROWBLINKCNT1],a ; blinking down arrow timing value 1 - ld a,$06 - ld [H_DOWNARROWBLINKCNT2],a ; blinking down arrow timing value 2 -.loop1 - xor a - ld [wPartyMonAnimCounter],a ; counter for pokemon shaking animation - call PlaceMenuCursor - call Delay3 -.loop2 - push hl - ld a,[wd09b] - and a ; is it a pokemon selection menu? - jr z,.getJoypadState - callba AnimatePartyMon ; shake mini sprite of selected pokemon -.getJoypadState - pop hl - call JoypadLowSensitivity - ld a,[hJoy5] - and a ; was a key pressed? - jr nz,.keyPressed - push hl - hlCoord 18, 11 ; coordinates of blinking down arrow in some menus - call HandleDownArrowBlinkTiming ; blink down arrow (if any) - pop hl - ld a,[wMenuJoypadPollCount] - dec a - jr z,.giveUpWaiting - jr .loop2 -.giveUpWaiting -; if a key wasn't pressed within the specified number of checks - pop af - ld [H_DOWNARROWBLINKCNT2],a - pop af - ld [H_DOWNARROWBLINKCNT1],a ; restore previous values - xor a - ld [wMenuWrappingEnabled],a ; disable menu wrapping - ret -.keyPressed - xor a - ld [wcc4b],a - ld a,[hJoy5] - ld b,a - bit 6,a ; pressed Up key? - jr z,.checkIfDownPressed -.upPressed - ld a,[wCurrentMenuItem] ; selected menu item - and a ; already at the top of the menu? - jr z,.alreadyAtTop -.notAtTop - dec a - ld [wCurrentMenuItem],a ; move selected menu item up one space - jr .checkOtherKeys -.alreadyAtTop - ld a,[wMenuWrappingEnabled] - and a ; is wrapping around enabled? - jr z,.noWrappingAround - ld a,[wMaxMenuItem] - ld [wCurrentMenuItem],a ; wrap to the bottom of the menu - jr .checkOtherKeys -.checkIfDownPressed - bit 7,a - jr z,.checkOtherKeys -.downPressed - ld a,[wCurrentMenuItem] - inc a - ld c,a - ld a,[wMaxMenuItem] - cp c - jr nc,.notAtBottom -.alreadyAtBottom - ld a,[wMenuWrappingEnabled] - and a ; is wrapping around enabled? - jr z,.noWrappingAround - ld c,$00 ; wrap from bottom to top -.notAtBottom - ld a,c - ld [wCurrentMenuItem],a -.checkOtherKeys - ld a,[wMenuWatchedKeys] - and b ; does the menu care about any of the pressed keys? - jp z,.loop1 -.checkIfAButtonOrBButtonPressed - ld a,[hJoy5] - and A_BUTTON | B_BUTTON - jr z,.skipPlayingSound -.AButtonOrBButtonPressed - push hl - ld hl,wFlags_0xcd60 - bit 5,[hl] - pop hl - jr nz,.skipPlayingSound - ld a,(SFX_02_40 - SFX_Headers_02) / 3 - call PlaySound ; play sound -.skipPlayingSound - pop af - ld [H_DOWNARROWBLINKCNT2],a - pop af - ld [H_DOWNARROWBLINKCNT1],a ; restore previous values - xor a - ld [wMenuWrappingEnabled],a ; disable menu wrapping - ld a,[hJoy5] - ret -.noWrappingAround - ld a,[wcc37] - and a ; should we return if the user tried to go past the top or bottom? - jr z,.checkOtherKeys - jr .checkIfAButtonOrBButtonPressed - -PlaceMenuCursor:: ; 3b7c (0:3b7c) - ld a,[wTopMenuItemY] - and a ; is the y coordinate 0? - jr z,.adjustForXCoord - ld hl,wTileMap - ld bc,SCREEN_WIDTH -.topMenuItemLoop - add hl,bc - dec a - jr nz,.topMenuItemLoop -.adjustForXCoord - ld a,[wTopMenuItemX] - ld b,0 - ld c,a - add hl,bc - push hl - ld a,[wLastMenuItem] - and a ; was the previous menu id 0? - jr z,.checkForArrow1 - push af - ld a,[hFlags_0xFFF6] - bit 1,a ; is the menu double spaced? - jr z,.doubleSpaced1 - ld bc,20 - jr .getOldMenuItemScreenPosition -.doubleSpaced1 - ld bc,40 -.getOldMenuItemScreenPosition - pop af -.oldMenuItemLoop - add hl,bc - dec a - jr nz,.oldMenuItemLoop -.checkForArrow1 - ld a,[hl] - cp a,"▶" ; was an arrow next to the previously selected menu item? - jr nz,.skipClearingArrow -.clearArrow - ld a,[wTileBehindCursor] - ld [hl],a -.skipClearingArrow - pop hl - ld a,[wCurrentMenuItem] - and a - jr z,.checkForArrow2 - push af - ld a,[hFlags_0xFFF6] - bit 1,a ; is the menu double spaced? - jr z,.doubleSpaced2 - ld bc,20 - jr .getCurrentMenuItemScreenPosition -.doubleSpaced2 - ld bc,40 -.getCurrentMenuItemScreenPosition - pop af -.currentMenuItemLoop - add hl,bc - dec a - jr nz,.currentMenuItemLoop -.checkForArrow2 - ld a,[hl] - cp a,"▶" ; has the right arrow already been placed? - jr z,.skipSavingTile ; if so, don't lose the saved tile - ld [wTileBehindCursor],a ; save tile before overwriting with right arrow -.skipSavingTile - ld a,"▶" ; place right arrow - ld [hl],a - ld a,l - ld [wMenuCursorLocation],a - ld a,h - ld [wMenuCursorLocation + 1],a - ld a,[wCurrentMenuItem] - ld [wLastMenuItem],a - ret - -; This is used to mark a menu cursor other than the one currently being -; manipulated. In the case of submenus, this is used to show the location of -; the menu cursor in the parent menu. In the case of swapping items in list, -; this is used to mark the item that was first chosen to be swapped. -PlaceUnfilledArrowMenuCursor:: ; 3bec (0:3bec) - ld b,a - ld a,[wMenuCursorLocation] - ld l,a - ld a,[wMenuCursorLocation + 1] - ld h,a - ld [hl],$ec ; outline of right arrow - ld a,b - ret - -; Replaces the menu cursor with a blank space. -EraseMenuCursor:: ; 3bf9 (0:3bf9) - ld a,[wMenuCursorLocation] - ld l,a - ld a,[wMenuCursorLocation + 1] - ld h,a - ld [hl]," " - ret - -; This toggles a blinking down arrow at hl on and off after a delay has passed. -; This is often called even when no blinking is occurring. -; The reason is that most functions that call this initialize H_DOWNARROWBLINKCNT1 to 0. -; The effect is that if the tile at hl is initialized with a down arrow, -; this function will toggle that down arrow on and off, but if the tile isn't -; initliazed with a down arrow, this function does nothing. -; That allows this to be called without worrying about if a down arrow should -; be blinking. -HandleDownArrowBlinkTiming:: ; 3c04 (0:3c04) - ld a,[hl] - ld b,a - ld a,$ee ; down arrow - cp b - jr nz,.downArrowOff -.downArrowOn - ld a,[H_DOWNARROWBLINKCNT1] - dec a - ld [H_DOWNARROWBLINKCNT1],a - ret nz - ld a,[H_DOWNARROWBLINKCNT2] - dec a - ld [H_DOWNARROWBLINKCNT2],a - ret nz - ld a," " - ld [hl],a - ld a,$ff - ld [H_DOWNARROWBLINKCNT1],a - ld a,$06 - ld [H_DOWNARROWBLINKCNT2],a - ret -.downArrowOff - ld a,[H_DOWNARROWBLINKCNT1] - and a - ret z - dec a - ld [H_DOWNARROWBLINKCNT1],a - ret nz - dec a - ld [H_DOWNARROWBLINKCNT1],a - ld a,[H_DOWNARROWBLINKCNT2] - dec a - ld [H_DOWNARROWBLINKCNT2],a - ret nz - ld a,$06 - ld [H_DOWNARROWBLINKCNT2],a - ld a,$ee ; down arrow - ld [hl],a - ret - -; The following code either enables or disables the automatic drawing of -; text boxes by DisplayTextID. Both functions cause DisplayTextID to wait -; for a button press after displaying text (unless [wcc47] is set). - -EnableAutoTextBoxDrawing:: ; 3c3c (0:3c3c) - xor a - jr AutoTextBoxDrawingCommon - -DisableAutoTextBoxDrawing:: ; 3c3f (0:3c3f) - ld a,$01 - -AutoTextBoxDrawingCommon:: ; 3c41 (0:3c41) - ld [wAutoTextBoxDrawingControl],a - xor a - ld [wDoNotWaitForButtonPressAfterDisplayingText],a ; make DisplayTextID wait for button press - ret - -PrintText:: ; 3c49 (0:3c49) -; Print text hl at (1, 14). - push hl - ld a,MESSAGE_BOX - ld [wTextBoxID],a - call DisplayTextBoxID - call UpdateSprites - call Delay3 - pop hl -Func_3c59:: ; 3c59 (0:3c59) - bcCoord 1, 14 - jp TextCommandProcessor - - -PrintNumber:: ; 3c5f -; Print the c-digit, b-byte value at de. -; Allows 2 to 7 digits. For 1-digit numbers, add -; the value to char "0" instead of calling PrintNumber. -; Flags LEADING_ZEROES and LEFT_ALIGN can be given -; in bits 7 and 6 of b respectively. -LEADING_ZEROES EQU 7 -LEFT_ALIGN EQU 6 - - push bc - xor a - ld [H_PASTLEADINGZEROES], a - ld [H_NUMTOPRINT], a - ld [H_NUMTOPRINT + 1], a - ld a, b - and $f - cp 1 - jr z, .byte - cp 2 - jr z, .word -.long - ld a, [de] - ld [H_NUMTOPRINT], a - inc de - ld a, [de] - ld [H_NUMTOPRINT + 1], a - inc de - ld a, [de] - ld [H_NUMTOPRINT + 2], a - jr .start - -.word - ld a, [de] - ld [H_NUMTOPRINT + 1], a - inc de - ld a, [de] - ld [H_NUMTOPRINT + 2], a - jr .start - -.byte - ld a, [de] - ld [H_NUMTOPRINT + 2], a - -.start - push de - - ld d, b - ld a, c - ld b, a - xor a - ld c, a - ld a, b - - cp 2 - jr z, .tens - cp 3 - jr z, .hundreds - cp 4 - jr z, .thousands - cp 5 - jr z, .ten_thousands - cp 6 - jr z, .hundred_thousands - -print_digit: macro - -if (\1) / $10000 - ld a, \1 / $10000 % $100 -else xor a -endc - ld [H_POWEROFTEN + 0], a - -if (\1) / $100 - ld a, \1 / $100 % $100 -else xor a -endc - ld [H_POWEROFTEN + 1], a - - ld a, \1 / $1 % $100 - ld [H_POWEROFTEN + 2], a - - call .PrintDigit - call .NextDigit -endm - -.millions print_digit 1000000 -.hundred_thousands print_digit 100000 -.ten_thousands print_digit 10000 -.thousands print_digit 1000 -.hundreds print_digit 100 - -.tens - ld c, 0 - ld a, [H_NUMTOPRINT + 2] -.mod - cp 10 - jr c, .ok - sub 10 - inc c - jr .mod -.ok - - ld b, a - ld a, [H_PASTLEADINGZEROES] - or c - ld [H_PASTLEADINGZEROES], a - jr nz, .past - call .PrintLeadingZero - jr .next -.past - ld a, "0" - add c - ld [hl], a -.next - - call .NextDigit -.ones - ld a, "0" - add b - ld [hli], a - pop de - dec de - pop bc - ret - -.PrintDigit: -; Divide by the current decimal place. -; Print the quotient, and keep the modulus. - ld c, 0 -.loop - ld a, [H_POWEROFTEN] - ld b, a - ld a, [H_NUMTOPRINT] - ld [H_SAVEDNUMTOPRINT], a - cp b - jr c, .underflow0 - sub b - ld [H_NUMTOPRINT], a - ld a, [H_POWEROFTEN + 1] - ld b, a - ld a, [H_NUMTOPRINT + 1] - ld [H_SAVEDNUMTOPRINT + 1], a - cp b - jr nc, .noborrow1 - - ld a, [H_NUMTOPRINT] - or 0 - jr z, .underflow1 - dec a - ld [H_NUMTOPRINT], a - ld a, [H_NUMTOPRINT + 1] -.noborrow1 - - sub b - ld [H_NUMTOPRINT + 1], a - ld a, [H_POWEROFTEN + 2] - ld b, a - ld a, [H_NUMTOPRINT + 2] - ld [H_SAVEDNUMTOPRINT + 2], a - cp b - jr nc, .noborrow2 - - ld a, [H_NUMTOPRINT + 1] - and a - jr nz, .borrowed - - ld a, [H_NUMTOPRINT] - and a - jr z, .underflow2 - dec a - ld [H_NUMTOPRINT], a - xor a -.borrowed - - dec a - ld [H_NUMTOPRINT + 1], a - ld a, [H_NUMTOPRINT + 2] -.noborrow2 - sub b - ld [H_NUMTOPRINT + 2], a - inc c - jr .loop - -.underflow2 - ld a, [H_SAVEDNUMTOPRINT + 1] - ld [H_NUMTOPRINT + 1], a -.underflow1 - ld a, [H_SAVEDNUMTOPRINT] - ld [H_NUMTOPRINT], a -.underflow0 - ld a, [H_PASTLEADINGZEROES] - or c - jr z, .PrintLeadingZero - - ld a, "0" - add c - ld [hl], a - ld [H_PASTLEADINGZEROES], a - ret - -.PrintLeadingZero: - bit LEADING_ZEROES, d - ret z - ld [hl], "0" - ret - -.NextDigit: -; Increment unless the number is left-aligned, -; leading zeroes are not printed, and no digits -; have been printed yet. - bit LEADING_ZEROES, d - jr nz, .inc - bit LEFT_ALIGN, d - jr z, .inc - ld a, [H_PASTLEADINGZEROES] - and a - ret z -.inc - inc hl - ret - - -CallFunctionInTable:: -JumpTable:: -; Call function a in jumptable hl. -; de is not preserved. - push hl - push de - push bc - add a - ld d, 0 - ld e, a - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - ld de, .returnAddress - push de - jp [hl] -.returnAddress - pop bc - pop de - pop hl - ret - - -IsInArray:: -; Search an array at hl for the value in a. -; Entry size is de bytes. -; Return count b and carry if found. - ld b, 0 - -IsInRestOfArray:: - ld c, a -.loop - ld a, [hl] - cp -1 - jr z, .notfound - cp c - jr z, .found - inc b - add hl, de - jr .loop - -.notfound - and a - ret - -.found - scf - ret - - -RestoreScreenTilesAndReloadTilePatterns:: ; 3dbe (0:3dbe) - call ClearSprites - ld a, $1 - ld [wUpdateSpritesEnabled], a - call ReloadMapSpriteTilePatterns - call LoadScreenTilesFromBuffer2 - call LoadTextBoxTilePatterns - call GoPAL_SET_CF1C - jr Delay3 - - -GBPalWhiteOutWithDelay3:: - call GBPalWhiteOut - -Delay3:: -; The bg map is updated each frame in thirds. -; Wait three frames to let the bg map fully update. - ld c, 3 - jp DelayFrames - -GBPalNormal:: -; Reset BGP and OBP0. - ld a, %11100100 ; 3210 - ld [rBGP], a - ld a, %11010000 ; 3100 - ld [rOBP0], a - ret - -GBPalWhiteOut:: -; White out all palettes. - xor a - ld [rBGP],a - ld [rOBP0],a - ld [rOBP1],a - ret - - -GoPAL_SET_CF1C:: ; 3ded (0:3ded) - ld b,$ff -GoPAL_SET:: ; 3def (0:3def) - ld a,[wOnSGB] - and a - ret z - predef_jump Func_71ddf - -GetHealthBarColor:: -; Return at hl the palette of -; an HP bar e pixels long. - ld a, e - cp 27 - ld d, 0 ; green - jr nc, .gotColor - cp 10 - inc d ; yellow - jr nc, .gotColor - inc d ; red -.gotColor - ld [hl], d - ret - -; Copy the current map's sprites' tile patterns to VRAM again after they have -; been overwritten by other tile patterns. -ReloadMapSpriteTilePatterns:: ; 3e08 (0:3e08) - ld hl, wFontLoaded - ld a, [hl] - push af - res 0, [hl] - push hl - xor a - ld [W_SPRITESETID], a - call DisableLCD - callba InitMapSprites - call EnableLCD - pop hl - pop af - ld [hl], a - call LoadPlayerSpriteGraphics - call LoadFontTilePatterns - jp UpdateSprites - - -GiveItem:: -; Give player quantity c of item b, -; and copy the item's name to wcf4b. -; Return carry on success. - ld a, b - ld [wd11e], a - ld [wcf91], a - ld a, c - ld [wcf96], a - ld hl,wNumBagItems - call AddItemToInventory - ret nc - call GetItemName - call CopyStringToCF4B - scf - ret - -GivePokemon:: -; Give the player monster b at level c. - ld a, b - ld [wcf91], a - ld a, c - ld [W_CURENEMYLVL], a - xor a - ld [wcc49], a - ld b, BANK(_GivePokemon) - ld hl, _GivePokemon - jp Bankswitch - - -Random:: -; Return a random number in a. -; For battles, use BattleRandom. - push hl - push de - push bc - callba Random_ - ld a, [hRandomAdd] - pop bc - pop de - pop hl - ret - - -INCLUDE "home/predef.asm" - - -Func_3ead:: ; 3ead (0:3ead) - ld b, BANK(CinnabarGymQuiz_1eb0a) - ld hl, CinnabarGymQuiz_1eb0a - jp Bankswitch - -CheckForHiddenObjectOrBookshelfOrCardKeyDoor:: ; 3eb5 (0:3eb5) - ld a, [H_LOADEDROMBANK] - push af - ld a, [hJoyHeld] - bit 0, a ; A button - jr z, .nothingFound -; A button is pressed - ld a, Bank(CheckForHiddenObject) - ld [MBC1RomBank], a - ld [H_LOADEDROMBANK], a - call CheckForHiddenObject - ld a, [$ffee] - and a - jr nz, .hiddenObjectNotFound - ld a, [wHiddenObjectFunctionRomBank] - ld [MBC1RomBank], a - ld [H_LOADEDROMBANK], a - ld de, .returnAddress - push de - jp [hl] -.returnAddress - xor a - jr .done -.hiddenObjectNotFound - callba PrintBookshelfText - ld a, [$ffdb] - and a - jr z, .done -.nothingFound - ld a, $ff -.done - ld [$ffeb], a - pop af - ld [MBC1RomBank], a - ld [H_LOADEDROMBANK], a - ret - -PrintPredefTextID:: ; 3ef5 (0:3ef5) - ld [H_DOWNARROWBLINKCNT2], a ; $ff8c - ld hl, TextPredefs - call SetMapTextPointer - ld hl, wcf11 - set 0, [hl] - call DisplayTextID - -RestoreMapTextPointer:: ; 3f05 (0:3f05) - ld hl, W_MAPTEXTPTR - ld a, [$ffec] - ld [hli], a - ld a, [$ffec + 1] - ld [hl], a - ret - -SetMapTextPointer:: ; 3f0f (0:3f0f) - ld a, [W_MAPTEXTPTR] - ld [$ffec], a - ld a, [W_MAPTEXTPTR + 1] - ld [$ffec + 1], a - ld a, l - ld [W_MAPTEXTPTR], a - ld a, h - ld [W_MAPTEXTPTR + 1], a - ret - -TextPredefs:: - add_tx_pre CardKeySuccessText ; 01 - add_tx_pre CardKeyFailText ; 02 - add_tx_pre RedBedroomPC ; 03 - add_tx_pre RedBedroomSNESText ; 04 - add_tx_pre PushStartText ; 05 - add_tx_pre SaveOptionText ; 06 - add_tx_pre StrengthsAndWeaknessesText ; 07 - add_tx_pre OakLabEmailText ; 08 - add_tx_pre AerodactylFossilText ; 09 - add_tx_pre Route15UpstairsBinocularsText ; 0A - add_tx_pre KabutopsFossilText ; 0B - add_tx_pre GymStatueText1 ; 0C - add_tx_pre GymStatueText2 ; 0D - add_tx_pre BookcaseText ; 0E - add_tx_pre ViridianCityPokecenterBenchGuyText ; 0F - add_tx_pre PewterCityPokecenterBenchGuyText ; 10 - add_tx_pre CeruleanCityPokecenterBenchGuyText ; 11 - add_tx_pre LavenderCityPokecenterBenchGuyText ; 12 - add_tx_pre VermilionCityPokecenterBenchGuyText ; 13 - add_tx_pre CeladonCityPokecenterBenchGuyText ; 14 - add_tx_pre CeladonCityHotelText ; 15 - add_tx_pre FuchsiaCityPokecenterBenchGuyText ; 16 - add_tx_pre CinnabarIslandPokecenterBenchGuyText ; 17 - add_tx_pre SaffronCityPokecenterBenchGuyText ; 18 - add_tx_pre MtMoonPokecenterBenchGuyText ; 19 - add_tx_pre RockTunnelPokecenterBenchGuyText ; 1A - add_tx_pre UnusedBenchGuyText1 ; 1B - add_tx_pre UnusedBenchGuyText2 ; 1C - add_tx_pre UnusedBenchGuyText3 ; 1D - add_tx_pre TerminatorText_62508 ; 1E - add_tx_pre PredefText1f ; 1F - add_tx_pre ViridianSchoolNotebook ; 20 - add_tx_pre ViridianSchoolBlackboard ; 21 - add_tx_pre JustAMomentText ; 22 - add_tx_pre PredefText23 ; 23 - add_tx_pre FoundHiddenItemText ; 24 - add_tx_pre HiddenItemBagFullText ; 25 - add_tx_pre VermilionGymTrashText ; 26 - add_tx_pre IndigoPlateauHQText ; 27 - add_tx_pre GameCornerOutOfOrderText ; 28 - add_tx_pre GameCornerOutToLunchText ; 29 - add_tx_pre GameCornerSomeonesKeysText ; 2A - add_tx_pre FoundHiddenCoinsText ; 2B - add_tx_pre DroppedHiddenCoinsText ; 2C - add_tx_pre BillsHouseMonitorText ; 2D - add_tx_pre BillsHouseInitiatedText ; 2E - add_tx_pre BillsHousePokemonList ; 2F - add_tx_pre MagazinesText ; 30 - add_tx_pre CinnabarGymQuiz ; 31 - add_tx_pre GameCornerNoCoinsText ; 32 - add_tx_pre GameCornerCoinCaseText ; 33 - add_tx_pre LinkCableHelp ; 34 - add_tx_pre TMNotebook ; 35 - add_tx_pre FightingDojoText ; 36 - add_tx_pre FightingDojoText_52a10 ; 37 - add_tx_pre FightingDojoText_52a1d ; 38 - add_tx_pre NewBicycleText ; 39 - add_tx_pre IndigoPlateauStatues ; 3A - add_tx_pre VermilionGymTrashSuccesText1 ; 3B - add_tx_pre VermilionGymTrashSuccesText2 ; 3C - add_tx_pre VermilionGymTrashSuccesText3 ; 3D - add_tx_pre VermilionGymTrashFailText ; 3E - add_tx_pre TownMapText ; 3F - add_tx_pre BookOrSculptureText ; 40 - add_tx_pre ElevatorText ; 41 - add_tx_pre PokemonStuffText ; 42 +
+; The rst vectors are unused.
+SECTION "rst 00", ROM0 [$00]
+ rst $38
+SECTION "rst 08", ROM0 [$08]
+ rst $38
+SECTION "rst 10", ROM0 [$10]
+ rst $38
+SECTION "rst 18", ROM0 [$18]
+ rst $38
+SECTION "rst 20", ROM0 [$20]
+ rst $38
+SECTION "rst 28", ROM0 [$28]
+ rst $38
+SECTION "rst 30", ROM0 [$30]
+ rst $38
+SECTION "rst 38", ROM0 [$38]
+ rst $38
+
+; Hardware interrupts
+SECTION "vblank", ROM0 [$40]
+ jp VBlank
+SECTION "hblank", ROM0 [$48]
+ rst $38
+SECTION "timer", ROM0 [$50]
+ jp Timer
+SECTION "serial", ROM0 [$58]
+ jp Serial
+SECTION "joypad", ROM0 [$60]
+ reti
+
+
+SECTION "Home", ROM0
+
+DisableLCD::
+ xor a
+ ld [rIF], a
+ ld a, [rIE]
+ ld b, a
+ res 0, a
+ ld [rIE], a
+
+.wait
+ ld a, [rLY]
+ cp LY_VBLANK
+ jr nz, .wait
+
+ ld a, [rLCDC]
+ and $ff ^ rLCDC_ENABLE_MASK
+ ld [rLCDC], a
+ ld a, b
+ ld [rIE], a
+ ret
+
+EnableLCD::
+ ld a, [rLCDC]
+ set rLCDC_ENABLE, a
+ ld [rLCDC], a
+ ret
+
+ClearSprites::
+ xor a
+ ld hl, wOAMBuffer
+ ld b, 40 * 4
+.loop
+ ld [hli], a
+ dec b
+ jr nz, .loop
+ ret
+
+HideSprites::
+ ld a, 160
+ ld hl, wOAMBuffer
+ ld de, 4
+ ld b, 40
+.loop
+ ld [hl], a
+ add hl, de
+ dec b
+ jr nz, .loop
+ ret
+
+INCLUDE "home/copy.asm"
+
+
+
+SECTION "Entry", ROM0 [$100]
+
+ nop
+ jp Start ; 01ab
+
+
+SECTION "Header", ROM0 [$104]
+
+ ; The header is generated by rgbfix.
+ ; The space here is allocated to prevent code from being overwritten.
+
+ ds $150 - $104
+
+
+
+SECTION "Main", ROM0
+
+Func_150:: ; 0150 (0:0150)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,b
+ call BankswitchCommon
+ ld a,[hli]
+ ld c,a
+ ld a,[hli]
+ ld b,a
+.loop
+ ld a,[hli]
+ ld d,a
+ ld a,$3
+.unknownloop
+ dec a
+ jr nz,.unknownloop
+
+ rept 7
+ call Func_199
+ call Func_1a5
+ endr
+
+ call Func_199
+ dec bc
+ ld a,c
+ or b
+ jr nz,.loop
+ pop af
+ call BankswitchCommon
+ ret
+
+Func_199:: ; 0199 (0:0199)
+ ld a,d
+ and $80
+ srl a
+ srl a
+ ld [rNR32],a
+ sla d
+ ret
+
+Func_1a5:: ; 01a5 (0:01a5)
+ ld a,$3
+.unknownloop2
+ dec a
+ jr nz,.unknownloop2
+ ret
+
+Start::
+ cp GBC
+ jr z, .gbc
+ xor a
+ jr .ok
+.gbc
+ ld a, $1
+.ok
+ ld [hGBC], a
+ jp Init
+
+Joypad:: ; 01b9
+ homecall_jump _Joypad
+
+ReadJoypad:: ; 01c8 (0:01c8)
+ homecall_jump ReadJoypad_
+
+INCLUDE "data/map_header_pointers.asm"
+INCLUDE "home/overworld.asm"
+
+
+CheckForUserInterruption:: ; 12f8 (0:12f8)
+; Return carry if Up+Select+B, Start or A are pressed in c frames.
+; Used only in the intro and title screen.
+ call DelayFrame
+
+ push bc
+ call JoypadLowSensitivity
+ pop bc
+
+ ld a, [hJoyHeld]
+ cp D_UP + SELECT + B_BUTTON
+ jr z, .input
+
+ ld a, [hJoy5]
+ and START | A_BUTTON
+ jr nz, .input
+
+ dec c
+ jr nz, CheckForUserInterruption
+
+ and a
+ ret
+
+.input
+ scf
+ ret
+
+; function to load position data for destination warp when switching maps
+; INPUT:
+; a = ID of destination warp within destination map
+LoadDestinationWarpPosition:: ; 1313 (0:1313)
+ ld b,a
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,[wPredefParentBank]
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ld a,b
+ add a
+ add a
+ ld c,a
+ ld b,0
+ add hl,bc
+ ld bc,4
+ ld de,wCurrentTileBlockMapViewPointer
+ call CopyData
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+
+DrawHPBar:: ; 1336 (0:1336)
+; Draw an HP bar d tiles long, and fill it to e pixels.
+; If c is nonzero, show at least a sliver regardless.
+; The right end of the bar changes with [wHPBarType].
+
+ push hl
+ push de
+ push bc
+
+ ; Left
+ ld a, $71 ; "HP:"
+ ld [hli], a
+ ld a, $62
+ ld [hli], a
+
+ push hl
+
+ ; Middle
+ ld a, $63 ; empty
+.draw
+ ld [hli],a
+ dec d
+ jr nz, .draw
+
+ ; Right
+ ld a,[wHPBarType]
+ dec a
+ ld a, $6d ; status screen and battle
+ jr z, .ok
+ dec a ; pokemon menu
+.ok
+ ld [hl],a
+
+ pop hl
+
+ ld a, e
+ and a
+ jr nz, .fill
+
+ ; If c iz nonzero, draw a pixel anyway.
+ ld a, c
+ and a
+ jr z, .done
+ ld e, 1
+
+.fill
+ ld a, e
+ sub 8
+ jr c, .partial
+ ld e, a
+ ld a, $6b ; full
+ ld [hli], a
+ ld a, e
+ and a
+ jr z, .done
+ jr .fill
+
+.partial
+ ; Fill remaining pixels at the end if necessary.
+ ld a, $63 ; empty
+ add e
+ ld [hl], a
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+
+; loads pokemon data from one of multiple sources to wLoadedMon
+; loads base stats to W_MONHDEXNUM
+; INPUT:
+; [wWhichPokemon] = index of pokemon within party/box
+; [wcc49] = source
+; 00: player's party
+; 01: enemy's party
+; 02: current box
+; 03: daycare
+; OUTPUT:
+; [wcf91] = pokemon ID
+; wLoadedMon = base address of pokemon data
+; W_MONHDEXNUM = base address of base stats
+LoadMonData:: ; 1372 (0:1372)
+ ld hl, LoadMonData_
+ ld b, BANK(LoadMonData_)
+ jp Bankswitch
+
+
+Func_137a:: ; 137a (0:137a)
+; Write c to [wMoves + b]. Unused.
+ ld hl, wMoves
+ ld e, b
+ ld d, 0
+ add hl, de
+ ld a, c
+ ld [hl], a
+ ret
+
+LoadFlippedFrontSpriteByMonIndex:: ; 1384 (0:1384)
+ ld a, 1
+ ld [W_SPRITEFLIPPED], a
+
+LoadFrontSpriteByMonIndex:: ; 1389 (0:1389)
+ push hl
+ ld a, [wd11e]
+ push af
+ ld a, [wcf91]
+ ld [wd11e], a
+ predef IndexToPokedex
+ ld hl, wd11e
+ ld a, [hl]
+ pop bc
+ ld [hl], b
+ and a
+ pop hl
+ jr z, .invalidDexNumber ; dex #0 invalid
+ cp NUM_POKEMON + 1
+ jr c, .validDexNumber ; dex >#151 invalid
+.invalidDexNumber
+ ld a, RHYDON ; $1
+ ld [wcf91], a
+ ret
+.validDexNumber
+ push hl
+ ld de, vFrontPic
+ call LoadMonFrontSprite
+ pop hl
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, Bank(asm_3f0d0)
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ xor a
+ ld [$ffe1], a
+ call asm_3f0d0
+ xor a
+ ld [W_SPRITEFLIPPED], a
+ pop af
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+
+
+PlayCry:: ; 13d0 (0:13d0)
+; Play monster a's cry.
+ call GetCryData
+ call PlaySound
+ jp WaitForSoundToFinish
+
+GetCryData:: ; 13d9 (0:13d9)
+; Load cry data for monster a.
+ dec a
+ ld c, a
+ ld b, 0
+ ld hl, CryData
+ add hl, bc
+ add hl, bc
+ add hl, bc
+
+ ld a, Bank(CryData)
+ call BankswitchHome
+ ld a, [hli]
+ ld b, a ; cry id
+ ld a, [hli]
+ ld [wc0f1], a
+ ld a, [hl]
+ ld [wc0f2], a
+ call BankswitchBack
+
+ ; Cry headers have 3 channels,
+ ; and start from index $14,
+ ; so add 3 times the cry id.
+ ld a, b
+ ld c, $14
+ rlca ; * 2
+ add b
+ add c
+ ret
+
+
+DisplayPartyMenu:: ; 13fc (0:13fc)
+ ld a,[hTilesetType]
+ push af
+ xor a
+ ld [hTilesetType],a
+ call GBPalWhiteOutWithDelay3
+ call ClearSprites
+ call PartyMenuInit
+ call DrawPartyMenu
+ jp HandlePartyMenuInput
+
+GoBackToPartyMenu:: ; 1411 (0:1411)
+ ld a,[hTilesetType]
+ push af
+ xor a
+ ld [hTilesetType],a
+ call PartyMenuInit
+ call RedrawPartyMenu
+ jp HandlePartyMenuInput
+
+PartyMenuInit:: ; 1420 (0:1420)
+ ld a, 1 ; hardcoded bank
+ call BankswitchHome
+ call LoadHpBarAndStatusTilePatterns
+ ld hl, wd730
+ set 6, [hl] ; turn off letter printing delay
+ xor a
+ ld [wcc49], a
+ ld [wcc37], a
+ ld hl, wTopMenuItemY
+ inc a
+ ld [hli], a ; top menu item Y
+ xor a
+ ld [hli], a ; top menu item X
+ ld a, [wcc2b]
+ push af
+ ld [hli], a ; current menu item ID
+ inc hl
+ ld a, [wPartyCount]
+ and a ; are there more than 0 pokemon in the party?
+ jr z, .storeMaxMenuItemID
+ dec a
+; if party is not empty, the max menu item ID is ([wPartyCount] - 1)
+; otherwise, it is 0
+.storeMaxMenuItemID
+ ld [hli], a ; max menu item ID
+ ld a, [wd11f]
+ and a
+ ld a, A_BUTTON + B_BUTTON
+ jr z, .next
+ xor a
+ ld [wd11f], a
+ inc a
+.next
+ ld [hli], a ; menu watched keys
+ pop af
+ ld [hl], a ; old menu item ID
+ ret
+
+HandlePartyMenuInput:: ; 145a (0:145a)
+ ld a,1
+ ld [wMenuWrappingEnabled],a
+ ld a,$40
+ ld [wd09b],a
+ call HandleMenuInputPokemonSelection
+ call PlaceUnfilledArrowMenuCursor
+ ld b,a
+ xor a
+ ld [wd09b],a
+ ld a,[wCurrentMenuItem]
+ ld [wcc2b],a
+ ld hl,wd730
+ res 6,[hl] ; turn on letter printing delay
+ ld a,[wMenuItemToSwap]
+ and a
+ jp nz,.swappingPokemon
+ pop af
+ ld [hTilesetType],a
+ bit 1,b
+ jr nz,.noPokemonChosen
+ ld a,[wPartyCount]
+ and a
+ jr z,.noPokemonChosen
+ ld a,[wCurrentMenuItem]
+ ld [wWhichPokemon],a
+ ld hl,wPartySpecies
+ ld b,0
+ ld c,a
+ add hl,bc
+ ld a,[hl]
+ ld [wcf91],a
+ ld [wBattleMonSpecies2],a
+ call BankswitchBack
+ and a
+ ret
+.noPokemonChosen
+ call BankswitchBack
+ scf
+ ret
+.swappingPokemon
+ bit 1,b ; was the B button pressed?
+ jr z,.handleSwap ; if not, handle swapping the pokemon
+.cancelSwap ; if the B button was pressed
+ callba ErasePartyMenuCursors
+ xor a
+ ld [wMenuItemToSwap],a
+ ld [wd07d],a
+ call RedrawPartyMenu
+ jr HandlePartyMenuInput
+.handleSwap
+ ld a,[wCurrentMenuItem]
+ ld [wWhichPokemon],a
+ callba SwitchPartyMon
+ jr HandlePartyMenuInput
+
+DrawPartyMenu:: ; 14d4 (0:14d4)
+ ld hl, DrawPartyMenu_
+ jr DrawPartyMenuCommon
+
+RedrawPartyMenu:: ; 14d9 (0:14d9)
+ ld hl, RedrawPartyMenu_
+
+DrawPartyMenuCommon:: ; 14dc (0:14dc)
+ ld b, BANK(RedrawPartyMenu_)
+ jp Bankswitch
+
+; prints a pokemon's status condition
+; INPUT:
+; de = address of status condition
+; hl = destination address
+PrintStatusCondition:: ; 14e1 (0:14e1)
+ push de
+ dec de
+ dec de ; de = address of current HP
+ ld a,[de]
+ ld b,a
+ dec de
+ ld a,[de]
+ or b ; is the pokemon's HP zero?
+ pop de
+ jr nz,PrintStatusConditionNotFainted
+; if the pokemon's HP is 0, print "FNT"
+ ld a,"F"
+ ld [hli],a
+ ld a,"N"
+ ld [hli],a
+ ld [hl],"T"
+ and a
+ ret
+PrintStatusConditionNotFainted ; 14f6
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,BANK(PrintStatusAilment)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call PrintStatusAilment ; print status condition
+ pop bc
+ ld a,b
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+; function to print pokemon level, leaving off the ":L" if the level is at least 100
+; INPUT:
+; hl = destination address
+; [wLoadedMonLevel] = level
+PrintLevel:: ; 150b (0:150b)
+ ld a,$6e ; ":L" tile ID
+ ld [hli],a
+ ld c,2 ; number of digits
+ ld a,[wLoadedMonLevel] ; level
+ cp a,100
+ jr c,PrintLevelCommon
+; if level at least 100, write over the ":L" tile
+ dec hl
+ inc c ; increment number of digits to 3
+ jr PrintLevelCommon
+
+; prints the level without leaving off ":L" regardless of level
+; INPUT:
+; hl = destination address
+; [wLoadedMonLevel] = level
+PrintLevelFull:: ; 151b (0:151b)
+ ld a,$6e ; ":L" tile ID
+ ld [hli],a
+ ld c,3 ; number of digits
+ ld a,[wLoadedMonLevel] ; level
+
+PrintLevelCommon:: ; 1523 (0:1523)
+ ld [wd11e],a
+ ld de,wd11e
+ ld b,$41 ; no leading zeroes, left-aligned, one byte
+ jp PrintNumber
+
+Func_152e:: ; 152e (0:152e)
+; Unused.
+ ld hl,wMoves
+ ld c,a
+ ld b,0
+ add hl,bc
+ ld a,[hl]
+ ret
+
+; copies the base stat data of a pokemon to W_MONHDEXNUM (W_MONHEADER)
+; INPUT:
+; [wd0b5] = pokemon ID
+GetMonHeader:: ; 1537 (0:1537)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,BANK(BaseStats)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ push bc
+ push de
+ push hl
+ ld a,[wd11e]
+ push af
+ ld a,[wd0b5]
+ ld [wd11e],a
+ ld de,FossilKabutopsPic
+ ld b,$66 ; size of Kabutops fossil and Ghost sprites
+ cp a,FOSSIL_KABUTOPS ; Kabutops fossil
+ jr z,.specialID
+ ld de,GhostPic
+ cp a,MON_GHOST ; Ghost
+ jr z,.specialID
+ ld de,FossilAerodactylPic
+ ld b,$77 ; size of Aerodactyl fossil sprite
+ cp a,FOSSIL_AERODACTYL ; Aerodactyl fossil
+ jr z,.specialID
+ cp a,MEW
+ jr z,.mew
+ predef IndexToPokedex ; convert pokemon ID in [wd11e] to pokedex number
+ ld a,[wd11e]
+ dec a
+ ld bc,28
+ ld hl,BaseStats
+ call AddNTimes
+ ld de,W_MONHEADER
+ ld bc,28
+ call CopyData
+ jr .done
+.specialID
+ ld hl,W_MONHSPRITEDIM
+ ld [hl],b ; write sprite dimensions
+ inc hl
+ ld [hl],e ; write front sprite pointer
+ inc hl
+ ld [hl],d
+ jr .done
+.mew
+ ld hl,MewBaseStats
+ ld de,W_MONHEADER
+ ld bc,28
+ ld a,BANK(MewBaseStats)
+ call FarCopyData
+.done
+ ld a,[wd0b5]
+ ld [W_MONHDEXNUM],a
+ pop af
+ ld [wd11e],a
+ pop hl
+ pop de
+ pop bc
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+; copy party pokemon's name to wcd6d
+GetPartyMonName2:: ; 15b4 (0:15b4)
+ ld a,[wWhichPokemon] ; index within party
+ ld hl,wPartyMonNicks
+
+; this is called more often
+GetPartyMonName:: ; 15ba (0:15ba)
+ push hl
+ push bc
+ call SkipFixedLengthTextEntries ; add 11 to hl, a times
+ ld de,wcd6d
+ push de
+ ld bc,11
+ call CopyData
+ pop de
+ pop bc
+ pop hl
+ ret
+
+; function to print a BCD (Binary-coded decimal) number
+; de = address of BCD number
+; hl = destination address
+; c = flags and length
+; bit 7: if set, do not print leading zeroes
+; if unset, print leading zeroes
+; bit 6: if set, left-align the string (do not pad empty digits with spaces)
+; if unset, right-align the string
+; bit 5: if set, print currency symbol at the beginning of the string
+; if unset, do not print the currency symbol
+; bits 0-4: length of BCD number in bytes
+; Note that bits 5 and 7 are modified during execution. The above reflects
+; their meaning at the beginning of the functions's execution.
+PrintBCDNumber:: ; 15cd (0:15cd)
+ ld b,c ; save flags in b
+ res 7,c
+ res 6,c
+ res 5,c ; c now holds the length
+ bit 5,b
+ jr z,.loop
+ bit 7,b
+ jr nz,.loop
+ ld [hl],"¥"
+ inc hl
+.loop
+ ld a,[de]
+ swap a
+ call PrintBCDDigit ; print upper digit
+ ld a,[de]
+ call PrintBCDDigit ; print lower digit
+ inc de
+ dec c
+ jr nz,.loop
+ bit 7,b ; were any non-zero digits printed?
+ jr z,.done ; if so, we are done
+.numberEqualsZero ; if every digit of the BCD number is zero
+ bit 6,b ; left or right alignment?
+ jr nz,.skipRightAlignmentAdjustment
+ dec hl ; if the string is right-aligned, it needs to be moved back one space
+.skipRightAlignmentAdjustment
+ bit 5,b
+ jr z,.skipCurrencySymbol
+ ld [hl],"¥"
+ inc hl
+.skipCurrencySymbol
+ ld [hl],"0"
+ call PrintLetterDelay
+ inc hl
+.done
+ ret
+
+PrintBCDDigit:: ; 1604 (0:1604)
+ and $f
+ and a
+ jr z,.zeroDigit
+.nonzeroDigit
+ bit 7,b ; have any non-space characters been printed?
+ jr z,.outputDigit
+; if bit 7 is set, then no numbers have been printed yet
+ bit 5,b ; print the currency symbol?
+ jr z,.skipCurrencySymbol
+ ld [hl],"¥"
+ inc hl
+ res 5,b
+.skipCurrencySymbol
+ res 7,b ; unset 7 to indicate that a nonzero digit has been reached
+.outputDigit
+ add a,"0"
+ ld [hli],a
+ jp PrintLetterDelay
+.zeroDigit
+ bit 7,b ; either printing leading zeroes or already reached a nonzero digit?
+ jr z,.outputDigit ; if so, print a zero digit
+ bit 6,b ; left or right alignment?
+ ret nz
+ inc hl ; if right-aligned, "print" a space by advancing the pointer
+ ret
+
+; uncompresses the front or back sprite of the specified mon
+; assumes the corresponding mon header is already loaded
+; hl contains offset to sprite pointer ($b for front or $d for back)
+UncompressMonSprite:: ; 1627 (0:1627)
+ ld bc,W_MONHEADER
+ add hl,bc
+ ld a,[hli]
+ ld [W_SPRITEINPUTPTR],a ; fetch sprite input pointer
+ ld a,[hl]
+ ld [W_SPRITEINPUTPTR+1],a
+; define (by index number) the bank that a pokemon's image is in
+; index = Mew, bank 1
+; index = Kabutops fossil, bank $B
+; index < $1F, bank 9
+; $1F ≤ index < $4A, bank $A
+; $4A ≤ index < $74, bank $B
+; $74 ≤ index < $99, bank $C
+; $99 ≤ index, bank $D
+ ld a,[wcf91] ; XXX name for this ram location
+ ld b,a
+ cp MEW
+ ld a,BANK(MewPicFront)
+ jr z,.GotBank
+ ld a,b
+ cp FOSSIL_KABUTOPS
+ ld a,BANK(FossilKabutopsPic)
+ jr z,.GotBank
+ ld a,b
+ cp TANGELA + 1
+ ld a,BANK(TangelaPicFront)
+ jr c,.GotBank
+ ld a,b
+ cp MOLTRES + 1
+ ld a,BANK(MoltresPicFront)
+ jr c,.GotBank
+ ld a,b
+ cp BEEDRILL + 2
+ ld a,BANK(BeedrillPicFront)
+ jr c,.GotBank
+ ld a,b
+ cp STARMIE + 1
+ ld a,BANK(StarmiePicFront)
+ jr c,.GotBank
+ ld a,BANK(VictreebelPicFront)
+.GotBank
+ jp UncompressSpriteData
+
+; de: destination location
+LoadMonFrontSprite:: ; 1665 (0:1665)
+ push de
+ ld hl, W_MONHFRONTSPRITE - W_MONHEADER
+ call UncompressMonSprite
+ ld hl, W_MONHSPRITEDIM
+ ld a, [hli]
+ ld c, a
+ pop de
+ ; fall through
+
+; postprocesses uncompressed sprite chunks to a 2bpp sprite and loads it into video ram
+; calculates alignment parameters to place both sprite chunks in the center of the 7*7 tile sprite buffers
+; de: destination location
+; a,c: sprite dimensions (in tiles of 8x8 each)
+LoadUncompressedSpriteData:: ; 1672 (0:1672)
+ push de
+ and $f
+ ld [H_SPRITEWIDTH], a ; each byte contains 8 pixels (in 1bpp), so tiles=bytes for width
+ ld b, a
+ ld a, $7
+ sub b ; 7-w
+ inc a ; 8-w
+ srl a ; (8-w)/2 ; horizontal center (in tiles, rounded up)
+ ld b, a
+ add a
+ add a
+ add a
+ sub b ; 7*((8-w)/2) ; skip for horizontal center (in tiles)
+ ld [H_SPRITEOFFSET], a
+ ld a, c
+ swap a
+ and $f
+ ld b, a
+ add a
+ add a
+ add a ; 8*tiles is height in bytes
+ ld [H_SPRITEHEIGHT], a ; $ff8c
+ ld a, $7
+ sub b ; 7-h ; skip for vertical center (in tiles, relative to current column)
+ ld b, a
+ ld a, [H_SPRITEOFFSET]
+ add b ; 7*((8-w)/2) + 7-h ; combined overall offset (in tiles)
+ add a
+ add a
+ add a ; 8*(7*((8-w)/2) + 7-h) ; combined overall offset (in bytes)
+ ld [H_SPRITEOFFSET], a
+ xor a
+ ld [$4000], a
+ ld hl, S_SPRITEBUFFER0
+ call ZeroSpriteBuffer ; zero buffer 0
+ ld de, S_SPRITEBUFFER1
+ ld hl, S_SPRITEBUFFER0
+ call AlignSpriteDataCentered ; copy and align buffer 1 to 0 (containing the MSB of the 2bpp sprite)
+ ld hl, S_SPRITEBUFFER1
+ call ZeroSpriteBuffer ; zero buffer 1
+ ld de, S_SPRITEBUFFER2
+ ld hl, S_SPRITEBUFFER1
+ call AlignSpriteDataCentered ; copy and align buffer 2 to 1 (containing the LSB of the 2bpp sprite)
+ pop de
+ jp InterlaceMergeSpriteBuffers
+
+; copies and aligns the sprite data properly inside the sprite buffer
+; sprite buffers are 7*7 tiles in size, the loaded sprite is centered within this area
+AlignSpriteDataCentered:: ; 16c2 (0:16c2)
+ ld a, [H_SPRITEOFFSET]
+ ld b, $0
+ ld c, a
+ add hl, bc
+ ld a, [H_SPRITEWIDTH] ; $ff8b
+.columnLoop
+ push af
+ push hl
+ ld a, [H_SPRITEHEIGHT] ; $ff8c
+ ld c, a
+.columnInnerLoop
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec c
+ jr nz, .columnInnerLoop
+ pop hl
+ ld bc, 7*8 ; 7 tiles
+ add hl, bc ; advance one full column
+ pop af
+ dec a
+ jr nz, .columnLoop
+ ret
+
+; fills the sprite buffer (pointed to in hl) with zeros
+ZeroSpriteBuffer:: ; 16df (0:16df)
+ ld bc, SPRITEBUFFERSIZE
+.nextByteLoop
+ xor a
+ ld [hli], a
+ dec bc
+ ld a, b
+ or c
+ jr nz, .nextByteLoop
+ ret
+
+; combines the (7*7 tiles, 1bpp) sprite chunks in buffer 0 and 1 into a 2bpp sprite located in buffer 1 through 2
+; in the resulting sprite, the rows of the two source sprites are interlaced
+; de: output address
+InterlaceMergeSpriteBuffers:: ; 16ea (0:16ea)
+ xor a
+ ld [$4000], a
+ push de
+ ld hl, S_SPRITEBUFFER2 + (SPRITEBUFFERSIZE - 1) ; destination: end of buffer 2
+ ld de, S_SPRITEBUFFER1 + (SPRITEBUFFERSIZE - 1) ; source 2: end of buffer 1
+ ld bc, S_SPRITEBUFFER0 + (SPRITEBUFFERSIZE - 1) ; source 1: end of buffer 0
+ ld a, SPRITEBUFFERSIZE/2 ; $c4
+ ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
+.interlaceLoop
+ ld a, [de]
+ dec de
+ ld [hld], a ; write byte of source 2
+ ld a, [bc]
+ dec bc
+ ld [hld], a ; write byte of source 1
+ ld a, [de]
+ dec de
+ ld [hld], a ; write byte of source 2
+ ld a, [bc]
+ dec bc
+ ld [hld], a ; write byte of source 1
+ ld a, [H_SPRITEINTERLACECOUNTER] ; $ff8b
+ dec a
+ ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
+ jr nz, .interlaceLoop
+ ld a, [W_SPRITEFLIPPED]
+ and a
+ jr z, .notFlipped
+ ld bc, 2*SPRITEBUFFERSIZE
+ ld hl, S_SPRITEBUFFER1
+.swapLoop
+ swap [hl] ; if flipped swap nybbles in all bytes
+ inc hl
+ dec bc
+ ld a, b
+ or c
+ jr nz, .swapLoop
+.notFlipped
+ pop hl
+ ld de, S_SPRITEBUFFER1
+ ld c, (2*SPRITEBUFFERSIZE)/16 ; $31, number of 16 byte chunks to be copied
+ ld a, [H_LOADEDROMBANK]
+ ld b, a
+ jp CopyVideoData
+
+
+INCLUDE "data/collision.asm"
+
+IsTilePassable:: ; 15c3 (0:15c3)
+; sets carry if tile is passable, resets carry otherwise
+ homecall_sf _IsTilePassable ; 1:4aaa
+ ret
+
+INCLUDE "home/copy2.asm"
+INCLUDE "home/text.asm"
+INCLUDE "home/vcopy.asm"
+INCLUDE "home/init.asm"
+INCLUDE "home/vblank.asm"
+INCLUDE "home/fade.asm"
+INCLUDE "home/serial.asm"
+INCLUDE "home/timer.asm"
+INCLUDE "home/audio.asm"
+
+
+UpdateSprites:: ; 2429 (0:2429)
+ ld a, [wUpdateSpritesEnabled]
+ dec a
+ ret nz
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, Bank(_UpdateSprites)
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ call _UpdateSprites
+ pop af
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+
+INCLUDE "data/mart_inventories.asm"
+
+TextScriptEndingChar:: ; 24d6 (0:24d6)
+ db "@"
+TextScriptEnd:: ; 24d7 (0:24d7)
+ ld hl,TextScriptEndingChar
+ ret
+
+ExclamationText:: ; 24db (0:24db)
+ TX_FAR _ExclamationText
+ db "@"
+
+GroundRoseText:: ; 24e0 (0:24e0)
+ TX_FAR _GroundRoseText
+ db "@"
+
+BoulderText:: ; 24e5 (0:24e5)
+ TX_FAR _BoulderText
+ db "@"
+
+MartSignText:: ; 24ea (0:24ea)
+ TX_FAR _MartSignText
+ db "@"
+
+PokeCenterSignText:: ; 24ef (0:24ef)
+ TX_FAR _PokeCenterSignText
+ db "@"
+
+Predef5CText:: ; 24f4 (0:24f4)
+; XXX better label (what does predef $5C do?)
+ db $08 ; asm
+ predef PickupItem
+ jp TextScriptEnd
+
+
+INCLUDE "home/pic.asm"
+
+
+ResetPlayerSpriteData:: ; 28a6 (0:28a6)
+ ld hl, wSpriteStateData1
+ call ResetPlayerSpriteData_ClearSpriteData
+ ld hl, wSpriteStateData2
+ call ResetPlayerSpriteData_ClearSpriteData
+ ld a, $1
+ ld [wSpriteStateData1], a
+ ld [wSpriteStateData2 + $0e], a
+ ld hl, wSpriteStateData1 + 4
+ ld [hl], $3c ; set Y screen pos
+ inc hl
+ inc hl
+ ld [hl], $40 ; set X screen pos
+ ret
+
+; overwrites sprite data with zeroes
+ResetPlayerSpriteData_ClearSpriteData:: ; 28c4 (0:28c4)
+ ld bc, $10
+ xor a
+ jp FillMemory
+
+Func_28cb:: ; 28cb (0:28cb)
+ ld a, [wMusicHeaderPointer]
+ and a
+ jr nz, .asm_28dc
+ ld a, [wd72c]
+ bit 1, a
+ ret nz
+ ld a, $77
+ ld [$ff24], a
+ ret
+.asm_28dc
+ ld a, [wcfc9]
+ and a
+ jr z, .asm_28e7
+ dec a
+ ld [wcfc9], a
+ ret
+.asm_28e7
+ ld a, [wcfc8]
+ ld [wcfc9], a
+ ld a, [$ff24]
+ and a
+ jr z, .asm_2903
+ ld b, a
+ and $f
+ dec a
+ ld c, a
+ ld a, b
+ and $f0
+ swap a
+ dec a
+ swap a
+ or c
+ ld [$ff24], a
+ ret
+.asm_2903
+ ld a, [wMusicHeaderPointer]
+ ld b, a
+ xor a
+ ld [wMusicHeaderPointer], a
+ ld a, $ff
+ ld [wc0ee], a
+ call PlaySound
+ ld a, [wc0f0]
+ ld [wc0ef], a
+ ld a, b
+ ld [wc0ee], a
+ jp PlaySound
+
+; this function is used to display sign messages, sprite dialog, etc.
+; INPUT: [$ff8c] = sprite ID or text ID
+DisplayTextID:: ; 2920 (0:2920)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ callba DisplayTextIDInit ; initialization
+ ld hl,wcf11
+ bit 0,[hl]
+ res 0,[hl]
+ jr nz,.skipSwitchToMapBank
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+.skipSwitchToMapBank
+ ld a,30 ; half a second
+ ld [H_FRAMECOUNTER],a ; used as joypad poll timer
+ ld hl,W_MAPTEXTPTR
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a ; hl = map text pointer
+ ld d,$00
+ ld a,[$ff8c] ; text ID
+ ld [wSpriteIndex],a
+ and a
+ jp z,DisplayStartMenu
+ cp a,$d3
+ jp z,DisplaySafariGameOverText
+ cp a,$d0
+ jp z,DisplayPokemonFaintedText
+ cp a,$d1
+ jp z,DisplayPlayerBlackedOutText
+ cp a,$d2
+ jp z,DisplayRepelWoreOffText
+ ld a,[W_NUMSPRITES]
+ ld e,a
+ ld a,[$ff8c] ; sprite ID
+ cp e
+ jr z,.spriteHandling
+ jr nc,.skipSpriteHandling
+.spriteHandling
+; get the text ID of the sprite
+ push hl
+ push de
+ push bc
+ callba UpdateSpriteFacingOffsetAndDelayMovement ; update the graphics of the sprite the player is talking to (to face the right direction)
+ pop bc
+ pop de
+ ld hl,W_MAPSPRITEDATA ; NPC text entries
+ ld a,[$ff8c]
+ dec a
+ add a
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ inc hl
+ ld a,[hl] ; a = text ID of the sprite
+ pop hl
+.skipSpriteHandling
+; look up the address of the text in the map's text entries
+ dec a
+ ld e,a
+ sla e
+ add hl,de
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a ; hl = address of the text
+ ld a,[hl] ; a = first byte of text
+; check first byte of text for special cases
+ cp a,$fe ; Pokemart NPC
+ jp z,DisplayPokemartDialogue
+ cp a,$ff ; Pokemon Center NPC
+ jp z,DisplayPokemonCenterDialogue
+ cp a,$fc ; Item Storage PC
+ jp z,FuncTX_ItemStoragePC
+ cp a,$fd ; Bill's PC
+ jp z,FuncTX_BillsPC
+ cp a,$f9 ; Pokemon Center PC
+ jp z,FuncTX_PokemonCenterPC
+ cp a,$f5 ; Vending Machine
+ jr nz,.notVendingMachine
+ callba VendingMachineMenu ; jump banks to vending machine routine
+ jr AfterDisplayingTextID
+.notVendingMachine
+ cp a,$f7 ; slot machine
+ jp z,FuncTX_SlotMachine
+ cp a,$f6 ; cable connection NPC in Pokemon Center
+ jr nz,.notSpecialCase
+ callab CableClubNPC
+ jr AfterDisplayingTextID
+.notSpecialCase
+ call Func_3c59 ; display the text
+ ld a,[wDoNotWaitForButtonPressAfterDisplayingText]
+ and a
+ jr nz,HoldTextDisplayOpen
+
+AfterDisplayingTextID:: ; 29d6 (0:29d6)
+ ld a,[wcc47]
+ and a
+ jr nz,HoldTextDisplayOpen
+ call WaitForTextScrollButtonPress ; wait for a button press after displaying all the text
+
+; loop to hold the dialogue box open as long as the player keeps holding down the A button
+HoldTextDisplayOpen:: ; 29df (0:29df)
+ call Joypad
+ ld a,[hJoyHeld]
+ bit 0,a ; is the A button being pressed?
+ jr nz,HoldTextDisplayOpen
+
+CloseTextDisplay:: ; 29e8 (0:29e8)
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ ld a,$90
+ ld [hWY],a ; move the window off the screen
+ call DelayFrame
+ call LoadGBPal
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED],a ; disable continuous WRAM to VRAM transfer each V-blank
+; loop to make sprites face the directions they originally faced before the dialogue
+ ld hl,wSpriteStateData2 + $19
+ ld c,$0f
+ ld de,$0010
+.restoreSpriteFacingDirectionLoop
+ ld a,[hl]
+ dec h
+ ld [hl],a
+ inc h
+ add hl,de
+ dec c
+ jr nz,.restoreSpriteFacingDirectionLoop
+ ld a,BANK(InitMapSprites)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call InitMapSprites ; reload sprite tile pattern data (since it was partially overwritten by text tile patterns)
+ ld hl,wFontLoaded
+ res 0,[hl]
+ ld a,[wd732]
+ bit 3,a ; used fly warp
+ call z,LoadPlayerSpriteGraphics
+ call LoadCurrentMapView
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ jp UpdateSprites
+
+DisplayPokemartDialogue:: ; 2a2e (0:2a2e)
+ push hl
+ ld hl,PokemartGreetingText
+ call PrintText
+ pop hl
+ inc hl
+ call LoadItemList
+ ld a,$02
+ ld [wListMenuID],a ; selects between subtypes of menus
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,Bank(DisplayPokemartDialogue_)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call DisplayPokemartDialogue_
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ jp AfterDisplayingTextID
+
+PokemartGreetingText:: ; 2a55 (0:2a55)
+ TX_FAR _PokemartGreetingText
+ db "@"
+
+LoadItemList:: ; 2a5a (0:2a5a)
+ ld a,$01
+ ld [wUpdateSpritesEnabled],a
+ ld a,h
+ ld [wd128],a
+ ld a,l
+ ld [wd129],a
+ ld de,wStringBuffer2 + 11
+.loop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ cp a,$ff
+ jr nz,.loop
+ ret
+
+DisplayPokemonCenterDialogue:: ; 2a72 (0:2a72)
+ xor a
+ ld [$ff8b],a
+ ld [$ff8c],a
+ ld [$ff8d],a
+ inc hl
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,Bank(DisplayPokemonCenterDialogue_)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call DisplayPokemonCenterDialogue_
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ jp AfterDisplayingTextID
+
+DisplaySafariGameOverText:: ; 2a90 (0:2a90)
+ callab PrintSafariGameOverText
+ jp AfterDisplayingTextID
+
+DisplayPokemonFaintedText:: ; 2a9b (0:2a9b)
+ ld hl,PokemonFaintedText
+ call PrintText
+ jp AfterDisplayingTextID
+
+PokemonFaintedText:: ; 2aa4 (0:2aa4)
+ TX_FAR _PokemonFaintedText
+ db "@"
+
+DisplayPlayerBlackedOutText:: ; 2aa9 (0:2aa9)
+ ld hl,PlayerBlackedOutText
+ call PrintText
+ ld a,[wd732]
+ res 5,a ; reset forced to use bike bit
+ ld [wd732],a
+ jp HoldTextDisplayOpen
+
+PlayerBlackedOutText:: ; 2aba (0:2aba)
+ TX_FAR _PlayerBlackedOutText
+ db "@"
+
+DisplayRepelWoreOffText:: ; 2abf (0:2abf)
+ ld hl,RepelWoreOffText
+ call PrintText
+ jp AfterDisplayingTextID
+
+RepelWoreOffText:: ; 2ac8 (0:2ac8)
+ TX_FAR _RepelWoreOffText
+ db "@"
+
+INCLUDE "engine/menu/start_menu.asm"
+
+; function to count how many bits are set in a string of bytes
+; INPUT:
+; hl = address of string of bytes
+; b = length of string of bytes
+; OUTPUT:
+; [wd11e] = number of set bits
+CountSetBits:: ; 2b7f (0:2b7f)
+ ld c,0
+.loop
+ ld a,[hli]
+ ld e,a
+ ld d,8
+.innerLoop ; count how many bits are set in the current byte
+ srl e
+ ld a,0
+ adc c
+ ld c,a
+ dec d
+ jr nz,.innerLoop
+ dec b
+ jr nz,.loop
+ ld a,c
+ ld [wd11e],a ; store number of set bits
+ ret
+
+; subtracts the amount the player paid from their money
+; sets carry flag if there is enough money and unsets carry flag if not
+SubtractAmountPaidFromMoney:: ; 2b96 (0:2b96)
+ ld b,BANK(SubtractAmountPaidFromMoney_)
+ ld hl,SubtractAmountPaidFromMoney_
+ jp Bankswitch
+
+; adds the amount the player sold to their money
+AddAmountSoldToMoney:: ; 2b9e (0:2b9e)
+ ld de,wPlayerMoney + 2
+ ld hl,$ffa1 ; total price of items
+ ld c,3 ; length of money in bytes
+ predef AddBCDPredef ; add total price to money
+ ld a,MONEY_BOX
+ ld [wTextBoxID],a
+ call DisplayTextBoxID ; redraw money text box
+ ld a, (SFX_02_5a - SFX_Headers_02) / 3
+ call PlaySoundWaitForCurrent ; play sound
+ jp WaitForSoundToFinish ; wait until sound is done playing
+
+; function to remove an item (in varying quantities) from the player's bag or PC box
+; INPUT:
+; HL = address of inventory (either wNumBagItems or wNumBoxItems)
+; [wWhichPokemon] = index (within the inventory) of the item to remove
+; [wcf96] = quantity to remove
+RemoveItemFromInventory:: ; 2bbb (0:2bbb)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,BANK(RemoveItemFromInventory_)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call RemoveItemFromInventory_
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+; function to add an item (in varying quantities) to the player's bag or PC box
+; INPUT:
+; HL = address of inventory (either wNumBagItems or wNumBoxItems)
+; [wcf91] = item ID
+; [wcf96] = item quantity
+; sets carry flag if successful, unsets carry flag if unsuccessful
+AddItemToInventory:: ; 2bcf (0:2bcf)
+ push bc
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,BANK(AddItemToInventory_)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call AddItemToInventory_
+ pop bc
+ ld a,b
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ pop bc
+ ret
+
+; INPUT:
+; [wListMenuID] = list menu ID
+; [wList] = address of the list (2 bytes)
+DisplayListMenuID:: ; 2be6 (0:2be6)
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED],a ; disable auto-transfer
+ ld a,1
+ ld [hJoy7],a ; joypad state update flag
+ ld a,[W_BATTLETYPE]
+ and a ; is it the Old Man battle?
+ jr nz,.specialBattleType
+ ld a,$01 ; hardcoded bank
+ jr .bankswitch
+.specialBattleType ; Old Man battle
+ ld a, Bank(DisplayBattleMenu)
+.bankswitch
+ call BankswitchHome
+ ld hl,wd730
+ set 6,[hl] ; turn off letter printing delay
+ xor a
+ ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped
+ ld [wd12a],a
+ ld a,[wList]
+ ld l,a
+ ld a,[wList + 1]
+ ld h,a ; hl = address of the list
+ ld a,[hl]
+ ld [wd12a],a ; [wd12a] = number of list entries
+ ld a,LIST_MENU_BOX
+ ld [wTextBoxID],a
+ call DisplayTextBoxID ; draw the menu text box
+ call UpdateSprites ; disable sprites behind the text box
+; the code up to .skipMovingSprites appears to be useless
+ hlCoord 4, 2 ; coordinates of upper left corner of menu text box
+ ld de,$090e ; height and width of menu text box
+ ld a,[wListMenuID]
+ and a ; is it a PC pokemon list?
+ jr nz,.skipMovingSprites
+ call UpdateSprites ; move sprites
+.skipMovingSprites
+ ld a,1 ; max menu item ID is 1 if the list has less than 2 entries
+ ld [wcc37],a
+ ld a,[wd12a]
+ cp a,2 ; does the list have less than 2 entries?
+ jr c,.setMenuVariables
+ ld a,2 ; max menu item ID is 2 if the list has at least 2 entries
+.setMenuVariables
+ ld [wMaxMenuItem],a
+ ld a,4
+ ld [wTopMenuItemY],a
+ ld a,5
+ ld [wTopMenuItemX],a
+ ld a,A_BUTTON | B_BUTTON | SELECT
+ ld [wMenuWatchedKeys],a
+ ld c,10
+ call DelayFrames
+
+DisplayListMenuIDLoop:: ; 2c53 (0:2c53)
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED],a ; disable transfer
+ call PrintListMenuEntries
+ ld a,1
+ ld [H_AUTOBGTRANSFERENABLED],a ; enable transfer
+ call Delay3
+ ld a,[W_BATTLETYPE]
+ and a ; is it the Old Man battle?
+ jr z,.notOldManBattle
+.oldManBattle
+ ld a,"▶"
+ Coorda 5, 4 ; place menu cursor in front of first menu entry
+ ld c,80
+ call DelayFrames
+ xor a
+ ld [wCurrentMenuItem],a
+ hlCoord 5, 4
+ ld a,l
+ ld [wMenuCursorLocation],a
+ ld a,h
+ ld [wMenuCursorLocation + 1],a
+ jr .buttonAPressed
+.notOldManBattle
+ call LoadGBPal
+ call HandleMenuInput
+ push af
+ call PlaceMenuCursor
+ pop af
+ bit 0,a ; was the A button pressed?
+ jp z,.checkOtherKeys
+.buttonAPressed
+ ld a,[wCurrentMenuItem]
+ call PlaceUnfilledArrowMenuCursor
+ ld a,$01
+ ld [wd12e],a
+ ld [wd12d],a
+ xor a
+ ld [wcc37],a
+ ld a,[wCurrentMenuItem]
+ ld c,a
+ ld a,[wListScrollOffset]
+ add c
+ ld c,a
+ ld a,[wd12a] ; number of list entries
+ and a ; is the list empty?
+ jp z,ExitListMenu ; if so, exit the menu
+ dec a
+ cp c ; did the player select Cancel?
+ jp c,ExitListMenu ; if so, exit the menu
+ ld a,c
+ ld [wWhichPokemon],a
+ ld a,[wListMenuID]
+ cp a,ITEMLISTMENU
+ jr nz,.skipMultiplying
+; if it's an item menu
+ sla c ; item entries are 2 bytes long, so multiply by 2
+.skipMultiplying
+ ld a,[wList]
+ ld l,a
+ ld a,[wList + 1]
+ ld h,a
+ inc hl ; hl = beginning of list entries
+ ld b,0
+ add hl,bc
+ ld a,[hl]
+ ld [wcf91],a
+ ld a,[wListMenuID]
+ and a ; is it a PC pokemon list?
+ jr z,.pokemonList
+ push hl
+ call GetItemPrice
+ pop hl
+ ld a,[wListMenuID]
+ cp a,ITEMLISTMENU
+ jr nz,.skipGettingQuantity
+; if it's an item menu
+ inc hl
+ ld a,[hl] ; a = item quantity
+ ld [wcf97],a
+.skipGettingQuantity
+ ld a,[wcf91]
+ ld [wd0b5],a
+ ld a,BANK(ItemNames)
+ ld [wPredefBank],a
+ call GetName
+ jr .storeChosenEntry
+.pokemonList
+ ld hl,wPartyCount
+ ld a,[wList]
+ cp l ; is it a list of party pokemon or box pokemon?
+ ld hl,wPartyMonNicks
+ jr z,.getPokemonName
+ ld hl, wBoxMonNicks ; box pokemon names
+.getPokemonName
+ ld a,[wWhichPokemon]
+ call GetPartyMonName
+.storeChosenEntry ; store the menu entry that the player chose and return
+ ld de,wcd6d
+ call CopyStringToCF4B ; copy name to wcf4b
+ ld a,$01
+ ld [wd12e],a
+ ld a,[wCurrentMenuItem]
+ ld [wd12d],a
+ xor a
+ ld [hJoy7],a ; joypad state update flag
+ ld hl,wd730
+ res 6,[hl] ; turn on letter printing delay
+ jp BankswitchBack
+.checkOtherKeys ; check B, SELECT, Up, and Down keys
+ bit 1,a ; was the B button pressed?
+ jp nz,ExitListMenu ; if so, exit the menu
+ bit 2,a ; was the select button pressed?
+ jp nz,HandleItemListSwapping ; if so, allow the player to swap menu entries
+ ld b,a
+ bit 7,b ; was Down pressed?
+ ld hl,wListScrollOffset
+ jr z,.upPressed
+.downPressed
+ ld a,[hl]
+ add a,3
+ ld b,a
+ ld a,[wd12a] ; number of list entries
+ cp b ; will going down scroll past the Cancel button?
+ jp c,DisplayListMenuIDLoop
+ inc [hl] ; if not, go down
+ jp DisplayListMenuIDLoop
+.upPressed
+ ld a,[hl]
+ and a
+ jp z,DisplayListMenuIDLoop
+ dec [hl]
+ jp DisplayListMenuIDLoop
+
+DisplayChooseQuantityMenu:: ; 2d57 (0:2d57)
+; text box dimensions/coordinates for just quantity
+ hlCoord 15, 9
+ ld b,1 ; height
+ ld c,3 ; width
+ ld a,[wListMenuID]
+ cp a,PRICEDITEMLISTMENU
+ jr nz,.drawTextBox
+; text box dimensions/coordinates for quantity and price
+ hlCoord 7, 9
+ ld b,1 ; height
+ ld c,11 ; width
+.drawTextBox
+ call TextBoxBorder
+ hlCoord 16, 10
+ ld a,[wListMenuID]
+ cp a,PRICEDITEMLISTMENU
+ jr nz,.printInitialQuantity
+ hlCoord 8, 10
+.printInitialQuantity
+ ld de,InitialQuantityText
+ call PlaceString
+ xor a
+ ld [wcf96],a ; initialize current quantity to 0
+ jp .incrementQuantity
+.waitForKeyPressLoop
+ call JoypadLowSensitivity
+ ld a,[hJoyPressed] ; newly pressed buttons
+ bit 0,a ; was the A button pressed?
+ jp nz,.buttonAPressed
+ bit 1,a ; was the B button pressed?
+ jp nz,.buttonBPressed
+ bit 6,a ; was Up pressed?
+ jr nz,.incrementQuantity
+ bit 7,a ; was Down pressed?
+ jr nz,.decrementQuantity
+ jr .waitForKeyPressLoop
+.incrementQuantity
+ ld a,[wcf97] ; max quantity
+ inc a
+ ld b,a
+ ld hl,wcf96 ; current quantity
+ inc [hl]
+ ld a,[hl]
+ cp b
+ jr nz,.handleNewQuantity
+; wrap to 1 if the player goes above the max quantity
+ ld a,1
+ ld [hl],a
+ jr .handleNewQuantity
+.decrementQuantity
+ ld hl,wcf96 ; current quantity
+ dec [hl]
+ jr nz,.handleNewQuantity
+; wrap to the max quantity if the player goes below 1
+ ld a,[wcf97] ; max quantity
+ ld [hl],a
+.handleNewQuantity
+ hlCoord 17, 10
+ ld a,[wListMenuID]
+ cp a,PRICEDITEMLISTMENU
+ jr nz,.printQuantity
+.printPrice
+ ld c,$03
+ ld a,[wcf96]
+ ld b,a
+ ld hl,$ff9f ; total price
+; initialize total price to 0
+ xor a
+ ld [hli],a
+ ld [hli],a
+ ld [hl],a
+.addLoop ; loop to multiply the individual price by the quantity to get the total price
+ ld de,$ffa1
+ ld hl,$ff8d
+ push bc
+ predef AddBCDPredef ; add the individual price to the current sum
+ pop bc
+ dec b
+ jr nz,.addLoop
+ ld a,[$ff8e]
+ and a ; should the price be halved (for selling items)?
+ jr z,.skipHalvingPrice
+ xor a
+ ld [$ffa2],a
+ ld [$ffa3],a
+ ld a,$02
+ ld [$ffa4],a
+ predef DivideBCDPredef3 ; halves the price
+; store the halved price
+ ld a,[$ffa2]
+ ld [$ff9f],a
+ ld a,[$ffa3]
+ ld [$ffa0],a
+ ld a,[$ffa4]
+ ld [$ffa1],a
+.skipHalvingPrice
+ hlCoord 12, 10
+ ld de,SpacesBetweenQuantityAndPriceText
+ call PlaceString
+ ld de,$ff9f ; total price
+ ld c,$a3
+ call PrintBCDNumber
+ hlCoord 9, 10
+.printQuantity
+ ld de,wcf96 ; current quantity
+ ld bc,$8102 ; print leading zeroes, 1 byte, 2 digits
+ call PrintNumber
+ jp .waitForKeyPressLoop
+.buttonAPressed ; the player chose to make the transaction
+ xor a
+ ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped
+ ret
+.buttonBPressed ; the player chose to cancel the transaction
+ xor a
+ ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped
+ ld a,$ff
+ ret
+
+InitialQuantityText:: ; 2e30 (0:2e30)
+ db "×01@"
+
+SpacesBetweenQuantityAndPriceText:: ; 2e34 (0:2e34)
+ db " @"
+
+ExitListMenu:: ; 2e3b (0:2e3b)
+ ld a,[wCurrentMenuItem]
+ ld [wd12d],a
+ ld a,$02
+ ld [wd12e],a
+ ld [wcc37],a
+ xor a
+ ld [hJoy7],a
+ ld hl,wd730
+ res 6,[hl]
+ call BankswitchBack
+ xor a
+ ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped
+ scf
+ ret
+
+PrintListMenuEntries:: ; 2e5a (0:2e5a)
+ hlCoord 5, 3
+ ld b,$09
+ ld c,$0e
+ call ClearScreenArea
+ ld a,[wList]
+ ld e,a
+ ld a,[wList + 1]
+ ld d,a
+ inc de ; de = beginning of list entries
+ ld a,[wListScrollOffset]
+ ld c,a
+ ld a,[wListMenuID]
+ cp a,ITEMLISTMENU
+ ld a,c
+ jr nz,.skipMultiplying
+; if it's an item menu
+; item entries are 2 bytes long, so multiply by 2
+ sla a
+ sla c
+.skipMultiplying
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry
+ hlCoord 6, 4 ; coordinates of first list entry name
+ ld b,4 ; print 4 names
+.loop
+ ld a,b
+ ld [wWhichPokemon],a
+ ld a,[de]
+ ld [wd11e],a
+ cp a,$ff
+ jp z,.printCancelMenuItem
+ push bc
+ push de
+ push hl
+ push hl
+ push de
+ ld a,[wListMenuID]
+ and a
+ jr z,.pokemonPCMenu
+ cp a,$01
+ jr z,.movesMenu
+.itemMenu
+ call GetItemName
+ jr .placeNameString
+.pokemonPCMenu
+ push hl
+ ld hl,wPartyCount
+ ld a,[wList]
+ cp l ; is it a list of party pokemon or box pokemon?
+ ld hl,wPartyMonNicks
+ jr z,.getPokemonName
+ ld hl, wBoxMonNicks ; box pokemon names
+.getPokemonName
+ ld a,[wWhichPokemon]
+ ld b,a
+ ld a,4
+ sub b
+ ld b,a
+ ld a,[wListScrollOffset]
+ add b
+ call GetPartyMonName
+ pop hl
+ jr .placeNameString
+.movesMenu
+ call GetMoveName
+.placeNameString
+ call PlaceString
+ pop de
+ pop hl
+ ld a,[wcf93]
+ and a ; should prices be printed?
+ jr z,.skipPrintingItemPrice
+.printItemPrice
+ push hl
+ ld a,[de]
+ ld de,ItemPrices
+ ld [wcf91],a
+ call GetItemPrice ; get price
+ pop hl
+ ld bc,20 + 5 ; 1 row down and 5 columns right
+ add hl,bc
+ ld c,$a3 ; no leading zeroes, right-aligned, print currency symbol, 3 bytes
+ call PrintBCDNumber
+.skipPrintingItemPrice
+ ld a,[wListMenuID]
+ and a
+ jr nz,.skipPrintingPokemonLevel
+.printPokemonLevel
+ ld a,[wd11e]
+ push af
+ push hl
+ ld hl,wPartyCount
+ ld a,[wList]
+ cp l ; is it a list of party pokemon or box pokemon?
+ ld a,$00
+ jr z,.next
+ ld a,$02
+.next
+ ld [wcc49],a
+ ld hl,wWhichPokemon
+ ld a,[hl]
+ ld b,a
+ ld a,$04
+ sub b
+ ld b,a
+ ld a,[wListScrollOffset]
+ add b
+ ld [hl],a
+ call LoadMonData ; load pokemon info
+ ld a,[wcc49]
+ and a ; is it a list of party pokemon or box pokemon?
+ jr z,.skipCopyingLevel
+.copyLevel
+ ld a,[wLoadedMonBoxLevel]
+ ld [wLoadedMonLevel],a
+.skipCopyingLevel
+ pop hl
+ ld bc,$001c
+ add hl,bc
+ call PrintLevel ; print level
+ pop af
+ ld [wd11e],a
+.skipPrintingPokemonLevel
+ pop hl
+ pop de
+ inc de
+ ld a,[wListMenuID]
+ cp a,ITEMLISTMENU
+ jr nz,.nextListEntry
+.printItemQuantity
+ ld a,[wd11e]
+ ld [wcf91],a
+ call IsKeyItem ; check if item is unsellable
+ ld a,[wd124]
+ and a ; is the item unsellable?
+ jr nz,.skipPrintingItemQuantity ; if so, don't print the quantity
+ push hl
+ ld bc,20 + 8 ; 1 row down and 8 columns right
+ add hl,bc
+ ld a,"×"
+ ld [hli],a
+ ld a,[wd11e]
+ push af
+ ld a,[de]
+ ld [wcf97],a
+ push de
+ ld de,wd11e
+ ld [de],a
+ ld bc,$0102
+ call PrintNumber
+ pop de
+ pop af
+ ld [wd11e],a
+ pop hl
+.skipPrintingItemQuantity
+ inc de
+ pop bc
+ inc c
+ push bc
+ inc c
+ ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ and a ; is an item being swapped?
+ jr z,.nextListEntry
+ sla a
+ cp c ; is it this item?
+ jr nz,.nextListEntry
+ dec hl
+ ld a,$ec ; unfilled right arrow menu cursor to indicate an item being swapped
+ ld [hli],a
+.nextListEntry
+ ld bc,2 * 20 ; 2 rows
+ add hl,bc
+ pop bc
+ inc c
+ dec b
+ jp nz,.loop
+ ld bc,-8
+ add hl,bc
+ ld a,$ee ; down arrow
+ ld [hl],a
+ ret
+.printCancelMenuItem
+ ld de,ListMenuCancelText
+ jp PlaceString
+
+ListMenuCancelText:: ; 2f97 (0:2f97)
+ db "CANCEL@"
+
+GetMonName:: ; 2f9e (0:2f9e)
+ push hl
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,BANK(MonsterNames) ; 07
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ld a,[wd11e]
+ dec a
+ ld hl,MonsterNames ; 421E
+ ld c,10
+ ld b,0
+ call AddNTimes
+ ld de,wcd6d
+ push de
+ ld bc,10
+ call CopyData
+ ld hl,wcd77
+ ld [hl], "@"
+ pop de
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ pop hl
+ ret
+
+GetItemName:: ; 2fcf (0:2fcf)
+; given an item ID at [wd11e], store the name of the item into a string
+; starting at wcd6d
+ push hl
+ push bc
+ ld a,[wd11e]
+ cp HM_01 ; is this a TM/HM?
+ jr nc,.Machine
+
+ ld [wd0b5],a
+ ld a,ITEM_NAME
+ ld [wNameListType],a
+ ld a,BANK(ItemNames)
+ ld [wPredefBank],a
+ call GetName
+ jr .Finish
+
+.Machine
+ call GetMachineName
+.Finish
+ ld de,wcd6d ; pointer to where item name is stored in RAM
+ pop bc
+ pop hl
+ ret
+
+GetMachineName:: ; 2ff3 (0:2ff3)
+; copies the name of the TM/HM in [wd11e] to wcd6d
+ push hl
+ push de
+ push bc
+ ld a,[wd11e]
+ push af
+ cp TM_01 ; is this a TM? [not HM]
+ jr nc,.WriteTM
+; if HM, then write "HM" and add 5 to the item ID, so we can reuse the
+; TM printing code
+ add 5
+ ld [wd11e],a
+ ld hl,HiddenPrefix ; points to "HM"
+ ld bc,2
+ jr .WriteMachinePrefix
+.WriteTM
+ ld hl,TechnicalPrefix ; points to "TM"
+ ld bc,2
+.WriteMachinePrefix
+ ld de,wcd6d
+ call CopyData
+
+; now get the machine number and convert it to text
+ ld a,[wd11e]
+ sub TM_01 - 1
+ ld b,$F6 ; "0"
+.FirstDigit
+ sub 10
+ jr c,.SecondDigit
+ inc b
+ jr .FirstDigit
+.SecondDigit
+ add 10
+ push af
+ ld a,b
+ ld [de],a
+ inc de
+ pop af
+ ld b,$F6 ; "0"
+ add b
+ ld [de],a
+ inc de
+ ld a,"@"
+ ld [de],a
+
+ pop af
+ ld [wd11e],a
+ pop bc
+ pop de
+ pop hl
+ ret
+
+TechnicalPrefix:: ; 303c (0:303c)
+ db "TM"
+HiddenPrefix:: ; 303e (0:303e)
+ db "HM"
+
+; sets carry if item is HM, clears carry if item is not HM
+; Input: a = item ID
+IsItemHM:: ; 3040 (0:3040)
+ cp a,HM_01
+ jr c,.notHM
+ cp a,TM_01
+ ret
+.notHM
+ and a
+ ret
+
+; sets carry if move is an HM, clears carry if move is not an HM
+; Input: a = move ID
+IsMoveHM:: ; 3049 (0:3049)
+ ld hl,HMMoves
+ ld de,1
+ jp IsInArray
+
+HMMoves:: ; 3052 (0:3052)
+ db CUT,FLY,SURF,STRENGTH,FLASH
+ db $ff ; terminator
+
+GetMoveName:: ; 3058 (0:3058)
+ push hl
+ ld a,MOVE_NAME
+ ld [wNameListType],a
+ ld a,[wd11e]
+ ld [wd0b5],a
+ ld a,BANK(MoveNames)
+ ld [wPredefBank],a
+ call GetName
+ ld de,wcd6d ; pointer to where move name is stored in RAM
+ pop hl
+ ret
+
+; reloads text box tile patterns, current map view, and tileset tile patterns
+ReloadMapData:: ; 3071 (0:3071)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ call DisableLCD
+ call LoadTextBoxTilePatterns
+ call LoadCurrentMapView
+ call LoadTilesetTilePatternData
+ call EnableLCD
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+; reloads tileset tile patterns
+ReloadTilesetTilePatterns:: ; 3090 (0:3090)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ call DisableLCD
+ call LoadTilesetTilePatternData
+ call EnableLCD
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+; shows the town map and lets the player choose a destination to fly to
+ChooseFlyDestination:: ; 30a9 (0:30a9)
+ ld hl,wd72e
+ res 4,[hl]
+ ld b, BANK(LoadTownMap_Fly)
+ ld hl, LoadTownMap_Fly
+ jp Bankswitch
+
+; causes the text box to close without waiting for a button press after displaying text
+DisableWaitingAfterTextDisplay:: ; 30b6 (0:30b6)
+ ld a,$01
+ ld [wDoNotWaitForButtonPressAfterDisplayingText],a
+ ret
+
+; uses an item
+; UseItem is used with dummy items to perform certain other functions as well
+; INPUT:
+; [wcf91] = item ID
+; OUTPUT:
+; [wcd6a] = success
+; 00: unsucessful
+; 01: successful
+; 02: not able to be used right now, no extra menu displayed (only certain items use this)
+UseItem:: ; 30bc (0:30bc)
+ ld b,BANK(UseItem_)
+ ld hl,UseItem_
+ jp Bankswitch
+
+; 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:: ; 30c4 (0:30c4)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,BANK(TossItem_)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call TossItem_
+ pop de
+ ld a,d
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+; 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:: ; 30d9 (0:30d9)
+ push hl
+ push de
+ push bc
+ callba IsKeyItem_
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; function to draw various text boxes
+; INPUT:
+; [wTextBoxID] = text box ID
+DisplayTextBoxID:: ; 30e8 (0:30e8)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,BANK(DisplayTextBoxID_)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call DisplayTextBoxID_
+ pop bc
+ ld a,b
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+; not zero if an NPC movement script is running, the player character is
+; automatically stepping down from a door, or joypad states are being simulated
+IsPlayerCharacterBeingControlledByGame:: ; 30fd (0:30fd)
+ ld a, [wNPCMovementScriptPointerTableNum]
+ and a
+ ret nz
+ ld a, [wd736]
+ bit 1, a ; currently stepping down from door bit
+ ret nz
+ ld a, [wd730]
+ and $80
+ ret
+
+RunNPCMovementScript:: ; 310e (0:310e)
+ ld hl, wd736
+ bit 0, [hl]
+ res 0, [hl]
+ jr nz, .playerStepOutFromDoor
+ ld a, [wNPCMovementScriptPointerTableNum]
+ and a
+ ret z
+ dec a
+ add a
+ ld d, 0
+ ld e, a
+ ld hl, .NPCMovementScriptPointerTables
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, [wNPCMovementScriptBank]
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ld a, [wNPCMovementScriptFunctionNum]
+ call CallFunctionInTable
+ pop af
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+.NPCMovementScriptPointerTables
+ dw ProfOakMovementScriptPointerTable
+ dw PewterMuseumGuyMovementScriptPointerTable
+ dw PewterGymGuyMovementScriptPointerTable
+.playerStepOutFromDoor
+ ld b, BANK(PlayerStepOutFromDoor)
+ ld hl, PlayerStepOutFromDoor
+ jp Bankswitch
+
+EndNPCMovementScript:: ; 314e (0:314e)
+ ld b, BANK(_EndNPCMovementScript)
+ ld hl, _EndNPCMovementScript
+ jp Bankswitch
+
+EmptyFunc2:: ; 3156 (0:3156)
+ ret
+
+; stores hl in [W_TRAINERHEADERPTR]
+StoreTrainerHeaderPointer:: ; 3157 (0:3157)
+ ld a, h
+ ld [W_TRAINERHEADERPTR], a
+ ld a, l
+ ld [W_TRAINERHEADERPTR+1], a
+ ret
+
+; executes the current map script from the function pointer array provided in hl.
+; a: map script index to execute (unless overridden by [wd733] bit 4)
+ExecuteCurMapScriptInTable:: ; 3160 (0:3160)
+ push af
+ push de
+ call StoreTrainerHeaderPointer
+ pop hl
+ pop af
+ push hl
+ ld hl, W_FLAGS_D733
+ bit 4, [hl]
+ res 4, [hl]
+ jr z, .useProvidedIndex ; test if map script index was overridden manually
+ ld a, [W_CURMAPSCRIPT]
+.useProvidedIndex
+ pop hl
+ ld [W_CURMAPSCRIPT], a
+ call CallFunctionInTable
+ ld a, [W_CURMAPSCRIPT]
+ ret
+
+LoadGymLeaderAndCityName:: ; 317f (0:317f)
+ push de
+ ld de, wGymCityName
+ ld bc, $11
+ call CopyData ; load city name
+ pop hl
+ ld de, wGymLeaderName
+ ld bc, $b
+ jp CopyData ; load gym leader name
+
+; reads specific information from trainer header (pointed to at W_TRAINERHEADERPTR)
+; a: offset in header data
+; 0 -> flag's bit (into wTrainerHeaderFlagBit)
+; 2 -> flag's byte ptr (into hl)
+; 4 -> before battle text (into hl)
+; 6 -> after battle text (into hl)
+; 8 -> end battle text (into hl)
+ReadTrainerHeaderInfo:: ; 3193 (0:3193)
+ push de
+ push af
+ ld d, $0
+ ld e, a
+ ld hl, W_TRAINERHEADERPTR
+ ld a, [hli]
+ ld l, [hl]
+ ld h, a
+ add hl, de
+ pop af
+ and a
+ jr nz, .nonZeroOffset
+ ld a, [hl]
+ ld [wTrainerHeaderFlagBit], a ; store flag's bit
+ jr .done
+.nonZeroOffset
+ cp $2
+ jr z, .readPointer ; read flag's byte ptr
+ cp $4
+ jr z, .readPointer ; read before battle text
+ cp $6
+ jr z, .readPointer ; read after battle text
+ cp $8
+ jr z, .readPointer ; read end battle text
+ cp $a
+ jr nz, .done
+ ld a, [hli] ; read end battle text (2) but override the result afterwards (XXX why, bug?)
+ ld d, [hl]
+ ld e, a
+ jr .done
+.readPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+.done
+ pop de
+ ret
+
+TrainerFlagAction::
+ predef_jump FlagActionPredef
+
+TalkToTrainer:: ; 31cc (0:31cc)
+ call StoreTrainerHeaderPointer
+ xor a
+ call ReadTrainerHeaderInfo ; read flag's bit
+ ld a, $2
+ call ReadTrainerHeaderInfo ; read flag's byte ptr
+ ld a, [wTrainerHeaderFlagBit]
+ ld c, a
+ ld b, $2
+ call TrainerFlagAction ; read trainer's flag
+ ld a, c
+ and a
+ jr z, .trainerNotYetFought ; test trainer's flag
+ ld a, $6
+ call ReadTrainerHeaderInfo ; print after battle text
+ jp PrintText
+.trainerNotYetFought ; 0x31ed
+ ld a, $4
+ call ReadTrainerHeaderInfo ; print before battle text
+ call PrintText
+ ld a, $a
+ call ReadTrainerHeaderInfo ; (?) does nothing apparently (maybe bug in ReadTrainerHeaderInfo)
+ push de
+ ld a, $8
+ call ReadTrainerHeaderInfo ; read end battle text
+ pop de
+ call SaveEndBattleTextPointers
+ ld hl, W_FLAGS_D733
+ set 4, [hl] ; activate map script index override (index is set below)
+ ld hl, wFlags_0xcd60
+ bit 0, [hl] ; test if player is already engaging the trainer (because the trainer saw the player)
+ ret nz
+; if the player talked to the trainer of his own volition
+ call EngageMapTrainer
+ ld hl, W_CURMAPSCRIPT
+ inc [hl] ; increment map script index before StartTrainerBattle increments it again (next script function is usually EndTrainerBattle)
+ jp StartTrainerBattle
+
+; checks if any trainers are seeing the player and wanting to fight
+CheckFightingMapTrainers:: ; 3219 (0:3219)
+ call CheckForEngagingTrainers
+ ld a, [wSpriteIndex]
+ cp $ff
+ jr nz, .trainerEngaging
+ xor a
+ ld [wSpriteIndex], a
+ ld [wTrainerHeaderFlagBit], a
+ ret
+.trainerEngaging
+ ld hl, W_FLAGS_D733
+ set 3, [hl]
+ ld [wcd4f], a
+ xor a
+ ld [wcd50], a
+ predef EmotionBubble
+ ld a, D_RIGHT | D_LEFT | D_UP | D_DOWN
+ ld [wJoyIgnore], a
+ xor a
+ ldh [$b4], a
+ call TrainerWalkUpToPlayer_Bank0
+ ld hl, W_CURMAPSCRIPT
+ inc [hl] ; increment map script index (next script function is usually DisplayEnemyTrainerTextAndStartBattle)
+ ret
+
+; display the before battle text after the enemy trainer has walked up to the player's sprite
+DisplayEnemyTrainerTextAndStartBattle:: ; 324c (0:324c)
+ ld a, [wd730]
+ and $1
+ ret nz ; return if the enemy trainer hasn't finished walking to the player's sprite
+ ld [wJoyIgnore], a
+ ld a, [wSpriteIndex]
+ ld [hSpriteIndexOrTextID], a
+ call DisplayTextID
+ ; fall through
+
+StartTrainerBattle:: ; 325d (0:325d)
+ xor a
+ ld [wJoyIgnore], a
+ call InitBattleEnemyParameters
+ ld hl, wd72d
+ set 6, [hl]
+ set 7, [hl]
+ ld hl, wd72e
+ set 1, [hl]
+ ld hl, W_CURMAPSCRIPT
+ inc [hl] ; increment map script index (next script function is usually EndTrainerBattle)
+ ret
+
+EndTrainerBattle:: ; 3275 (0:3275)
+ ld hl, wd126
+ set 5, [hl]
+ set 6, [hl]
+ ld hl, wd72d
+ res 7, [hl]
+ ld hl, wFlags_0xcd60
+ res 0, [hl] ; player is no longer engaged by any trainer
+ ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+ cp $ff
+ jp z, ResetButtonPressedAndMapScript
+ ld a, $2
+ call ReadTrainerHeaderInfo
+ ld a, [wTrainerHeaderFlagBit]
+ ld c, a
+ ld b, $1
+ call TrainerFlagAction ; flag trainer as fought
+ ld a, [W_ENEMYMONORTRAINERCLASS]
+ cp $c8
+ jr nc, .skipRemoveSprite ; test if trainer was fought (in that case skip removing the corresponding sprite)
+ ld hl, W_MISSABLEOBJECTLIST
+ ld de, $2
+ ld a, [wSpriteIndex]
+ call IsInArray ; search for sprite ID
+ inc hl
+ ld a, [hl]
+ ld [wcc4d], a ; load corresponding missable object index and remove it
+ predef HideObject
+.skipRemoveSprite
+ ld hl, wd730
+ bit 4, [hl]
+ res 4, [hl]
+ ret nz
+
+ResetButtonPressedAndMapScript:: ; 32c1 (0:32c1)
+ xor a
+ ld [wJoyIgnore], a
+ ld [hJoyHeld], a
+ ld [hJoyPressed], a
+ ld [hJoyReleased], a
+ ld [W_CURMAPSCRIPT], a ; reset battle status
+ ret
+
+; calls TrainerWalkUpToPlayer
+TrainerWalkUpToPlayer_Bank0:: ; 32cf (0:32cf)
+ ld b, BANK(TrainerWalkUpToPlayer)
+ ld hl, TrainerWalkUpToPlayer
+ jp Bankswitch
+
+; sets opponent type and mon set/lvl based on the engaging trainer data
+InitBattleEnemyParameters:: ; 32d7 (0:32d7)
+ ld a, [wEngagedTrainerClass]
+ ld [W_CUROPPONENT], a ; wd059
+ ld [W_ENEMYMONORTRAINERCLASS], a
+ cp $c8
+ ld a, [wEngagedTrainerSet] ; wcd2e
+ jr c, .noTrainer
+ ld [W_TRAINERNO], a ; wd05d
+ ret
+.noTrainer
+ ld [W_CURENEMYLVL], a ; W_CURENEMYLVL
+ ret
+
+GetSpritePosition1:: ; 32ef (0:32ef)
+ ld hl, _GetSpritePosition1
+ jr asm_3301
+
+GetSpritePosition2:: ; 32f4 (0:32f4)
+ ld hl, _GetSpritePosition2
+ jr asm_3301 ; 0x32f7 $8
+
+SetSpritePosition1:: ; 32f9 (0:32f9)
+ ld hl, _SetSpritePosition1
+ jr asm_3301
+
+SetSpritePosition2:: ; 32fe (0:32fe)
+ ld hl, _SetSpritePosition2
+asm_3301:: ; 3301 (0:3301)
+ ld b, BANK(_GetSpritePosition1) ; BANK(_GetSpritePosition2), BANK(_SetSpritePosition1), BANK(_SetSpritePosition2)
+ jp Bankswitch ; indirect jump to one of the four functions
+
+CheckForEngagingTrainers:: ; 3306 (0:3306)
+ xor a
+ call ReadTrainerHeaderInfo ; read trainer flag's bit (unused)
+ ld d, h ; store trainer header address in de
+ ld e, l
+.trainerLoop
+ call StoreTrainerHeaderPointer ; set trainer header pointer to current trainer
+ ld a, [de]
+ ld [wSpriteIndex], a ; store trainer flag's bit
+ ld [wTrainerHeaderFlagBit], a
+ cp $ff
+ ret z
+ ld a, $2
+ call ReadTrainerHeaderInfo ; read trainer flag's byte ptr
+ ld b, $2
+ ld a, [wTrainerHeaderFlagBit]
+ ld c, a
+ call TrainerFlagAction ; read trainer flag
+ ld a, c
+ and a
+ jr nz, .trainerAlreadyFought
+ push hl
+ push de
+ push hl
+ xor a
+ call ReadTrainerHeaderInfo ; get trainer header pointer
+ inc hl
+ ld a, [hl] ; read trainer engage distance
+ pop hl
+ ld [wTrainerEngageDistance], a
+ ld a, [wSpriteIndex]
+ swap a
+ ld [wTrainerSpriteOffset], a ; wWhichTrade
+ predef TrainerEngage
+ pop de
+ pop hl
+ ld a, [wTrainerSpriteOffset] ; wWhichTrade
+ and a
+ ret nz ; break if the trainer is engaging
+.trainerAlreadyFought
+ ld hl, $c
+ add hl, de
+ ld d, h
+ ld e, l
+ jr .trainerLoop
+
+; hl = text if the player wins
+; de = text if the player loses
+SaveEndBattleTextPointers:: ; 3354 (0:3354)
+ ld a, [H_LOADEDROMBANK]
+ ld [wEndBattleTextRomBank], a
+ ld a, h
+ ld [wEndBattleWinTextPointer], a
+ ld a, l
+ ld [wEndBattleWinTextPointer + 1], a
+ ld a, d
+ ld [wEndBattleLoseTextPointer], a
+ ld a, e
+ ld [wEndBattleLoseTextPointer + 1], a
+ ret
+
+; loads data of some trainer on the current map and plays pre-battle music
+; [wSpriteIndex]: sprite ID of trainer who is engaged
+EngageMapTrainer:: ; 336a (0:336a)
+ ld hl, W_MAPSPRITEEXTRADATA
+ ld d, $0
+ ld a, [wSpriteIndex]
+ dec a
+ add a
+ ld e, a
+ add hl, de ; seek to engaged trainer data
+ ld a, [hli] ; load trainer class
+ ld [wEngagedTrainerClass], a
+ ld a, [hl] ; load trainer mon set
+ ld [wEnemyMonAttackMod], a ; wcd2e
+ jp PlayTrainerMusic
+
+PrintEndBattleText:: ; 3381 (0:3381)
+ push hl
+ ld hl, wd72d
+ bit 7, [hl]
+ res 7, [hl]
+ pop hl
+ ret z
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, [wEndBattleTextRomBank]
+ ld [H_LOADEDROMBANK], a
+ ld [MBC1RomBank], a
+ push hl
+ callba SaveTrainerName
+ ld hl, TrainerEndBattleText
+ call PrintText
+ pop hl
+ pop af
+ ld [H_LOADEDROMBANK], a
+ ld [MBC1RomBank], a
+ callba FreezeEnemyTrainerSprite
+ jp WaitForSoundToFinish
+
+GetSavedEndBattleTextPointer:: ; 33b7 (0:33b7)
+ ld a, [wBattleResult]
+ and a
+; won battle
+ jr nz, .lostBattle
+ ld a, [wEndBattleWinTextPointer]
+ ld h, a
+ ld a, [wEndBattleWinTextPointer + 1]
+ ld l, a
+ ret
+.lostBattle
+ ld a, [wEndBattleLoseTextPointer]
+ ld h, a
+ ld a, [wEndBattleLoseTextPointer + 1]
+ ld l, a
+ ret
+
+TrainerEndBattleText:: ; 33cf (0:33cf)
+ TX_FAR _TrainerNameText
+ db $08
+ call GetSavedEndBattleTextPointer
+ call TextCommandProcessor
+ jp TextScriptEnd
+
+; XXX unused?
+Func_33dd:: ; 33dd (0:33dd)
+ ld a, [wFlags_0xcd60]
+ bit 0, a
+ ret nz
+ call EngageMapTrainer
+ xor a
+ ret
+
+PlayTrainerMusic:: ; 33e8 (0:33e8)
+ ld a, [wEngagedTrainerClass]
+ cp $c8 + SONY1
+ ret z
+ cp $c8 + SONY2
+ ret z
+ cp $c8 + SONY3
+ ret z
+ ld a, [W_GYMLEADERNO] ; W_GYMLEADERNO
+ and a
+ ret nz
+ xor a
+ ld [wMusicHeaderPointer], a
+ ld a, $ff
+ call PlaySound ; stop music
+ ld a, BANK(Music_MeetEvilTrainer)
+ ld [wc0ef], a
+ ld [wc0f0], a
+ ld a, [wEngagedTrainerClass]
+ ld b, a
+ ld hl, EvilTrainerList
+.evilTrainerListLoop
+ ld a, [hli]
+ cp $ff
+ jr z, .noEvilTrainer
+ cp b
+ jr nz, .evilTrainerListLoop
+ ld a, MUSIC_MEET_EVIL_TRAINER
+ jr .PlaySound
+.noEvilTrainer
+ ld hl, FemaleTrainerList
+.femaleTrainerListLoop
+ ld a, [hli]
+ cp $ff
+ jr z, .maleTrainer
+ cp b
+ jr nz, .femaleTrainerListLoop
+ ld a, MUSIC_MEET_FEMALE_TRAINER
+ jr .PlaySound
+.maleTrainer
+ ld a, MUSIC_MEET_MALE_TRAINER
+.PlaySound
+ ld [wc0ee], a
+ jp PlaySound
+
+INCLUDE "data/trainer_types.asm"
+
+; checks if the player's coordinates match an arrow movement tile's coordinates
+; and if so, decodes the RLE movement data
+; b = player Y
+; c = player X
+DecodeArrowMovementRLE:: ; 3442 (0:3442)
+ ld a, [hli]
+ cp $ff
+ ret z ; no match in the list
+ cp b
+ jr nz, .nextArrowMovementTileEntry1
+ ld a, [hli]
+ cp c
+ jr nz, .nextArrowMovementTileEntry2
+ ld a, [hli]
+ ld d, [hl]
+ ld e, a
+ ld hl, wSimulatedJoypadStatesEnd
+ call DecodeRLEList
+ dec a
+ ld [wSimulatedJoypadStatesIndex], a
+ ret
+.nextArrowMovementTileEntry1
+ inc hl
+.nextArrowMovementTileEntry2
+ inc hl
+ inc hl
+ jr DecodeArrowMovementRLE
+
+FuncTX_ItemStoragePC:: ; 3460 (0:3460)
+ call SaveScreenTilesToBuffer2
+ ld b, BANK(PlayerPC)
+ ld hl, PlayerPC
+ jr bankswitchAndContinue
+
+FuncTX_BillsPC:: ; 346a (0:346a)
+ call SaveScreenTilesToBuffer2
+ ld b, BANK(BillsPC_)
+ ld hl, BillsPC_
+ jr bankswitchAndContinue
+
+FuncTX_SlotMachine:: ; 3474 (0:3474)
+; XXX find a better name for this function
+; special_F7
+ ld b,BANK(CeladonPrizeMenu)
+ ld hl,CeladonPrizeMenu
+bankswitchAndContinue:: ; 3479 (0:3479)
+ call Bankswitch
+ jp HoldTextDisplayOpen ; continue to main text-engine function
+
+FuncTX_PokemonCenterPC:: ; 347f (0:347f)
+ ld b, BANK(ActivatePC)
+ ld hl, ActivatePC
+ jr bankswitchAndContinue
+
+StartSimulatingJoypadStates:: ; 3486 (0:3486)
+ xor a
+ ld [wOverrideSimulatedJoypadStatesMask], a
+ ld [wSpriteStateData2 + $06], a ; player's sprite movement byte 1
+ ld hl, wd730
+ set 7, [hl]
+ ret
+
+IsItemInBag:: ; 3493 (0:3493)
+; given an item_id in b
+; set zero flag if item isn't in player's bag
+; else reset zero flag
+; related to Pokémon Tower and ghosts
+ predef IsItemInBag_
+ ld a,b
+ and a
+ ret
+
+DisplayPokedex:: ; 349b (0:349b)
+ ld [wd11e], a
+ ld b, BANK(Func_7c18)
+ ld hl, Func_7c18
+ jp Bankswitch
+
+SetSpriteFacingDirectionAndDelay:: ; 34a6 (0:34a6)
+ call SetSpriteFacingDirection
+ ld c, $6
+ jp DelayFrames
+
+SetSpriteFacingDirection:: ; 34ae (0:34ae)
+ ld a, $9
+ ld [H_SPRITEDATAOFFSET], a
+ call GetPointerWithinSpriteStateData1
+ ld a, [$ff8d]
+ ld [hl], a
+ ret
+
+SetSpriteImageIndexAfterSettingFacingDirection:: ; 34b9 (0:34b9)
+ ld de, -7
+ add hl, de
+ ld [hl], a
+ ret
+
+; tests if the player's coordinates are in a specified array
+; INPUT:
+; hl = address of array
+; OUTPUT:
+; [wWhichTrade] = if there is match, the matching array index
+; sets carry if the coordinates are in the array, clears carry if not
+ArePlayerCoordsInArray:: ; 34bf (0:34bf)
+ ld a,[W_YCOORD]
+ ld b,a
+ ld a,[W_XCOORD]
+ ld c,a
+ ; fallthrough
+
+CheckCoords:: ; 34c7 (0:34c7)
+ xor a
+ ld [wWhichTrade],a
+.loop
+ ld a,[hli]
+ cp a,$ff ; reached terminator?
+ jr z,.notInArray
+ push hl
+ ld hl,wWhichTrade
+ inc [hl]
+ pop hl
+.compareYCoord
+ cp b
+ jr z,.compareXCoord
+ inc hl
+ jr .loop
+.compareXCoord
+ ld a,[hli]
+ cp c
+ jr nz,.loop
+.inArray
+ scf
+ ret
+.notInArray
+ and a
+ ret
+
+; tests if a boulder's coordinates are in a specified array
+; INPUT:
+; hl = address of array
+; [H_SPRITEINDEX] = index of boulder sprite
+; OUTPUT:
+; [wWhichTrade] = if there is match, the matching array index
+; sets carry if the coordinates are in the array, clears carry if not
+CheckBoulderCoords:: ; 34e4 (0:34e4)
+ push hl
+ ld hl, wSpriteStateData2 + $04
+ ld a, [H_SPRITEINDEX]
+ swap a
+ ld d, $0
+ ld e, a
+ add hl, de
+ ld a, [hli]
+ sub $4 ; because sprite coordinates are offset by 4
+ ld b, a
+ ld a, [hl]
+ sub $4 ; because sprite coordinates are offset by 4
+ ld c, a
+ pop hl
+ jp CheckCoords
+
+GetPointerWithinSpriteStateData1:: ; 34fc (0:34fc)
+ ld h, $c1
+ jr _GetPointerWithinSpriteStateData
+
+GetPointerWithinSpriteStateData2:: ; 3500 (0:3500)
+ ld h, $c2
+
+_GetPointerWithinSpriteStateData:
+ ld a, [H_SPRITEDATAOFFSET]
+ ld b, a
+ ld a, [H_SPRITEINDEX]
+ swap a
+ add b
+ ld l, a
+ ret
+
+; decodes a $ff-terminated RLEncoded list
+; each entry is a pair of bytes <byte value> <repetitions>
+; the final $ff will be replicated in the output list and a contains the number of bytes written
+; de: input list
+; hl: output list
+DecodeRLEList:: ; 350c (0:350c)
+ xor a
+ ld [wRLEByteCount], a ; count written bytes here
+.listLoop
+ ld a, [de]
+ cp $ff
+ jr z, .endOfList
+ ld [H_DOWNARROWBLINKCNT1], a ; store byte value to be written
+ inc de
+ ld a, [de]
+ ld b, $0
+ ld c, a ; number of bytes to be written
+ ld a, [wRLEByteCount]
+ add c
+ ld [wRLEByteCount], a ; update total number of written bytes
+ ld a, [H_DOWNARROWBLINKCNT1] ; $ff8b
+ call FillMemory ; write a c-times to output
+ inc de
+ jr .listLoop
+.endOfList
+ ld a, $ff
+ ld [hl], a ; write final $ff
+ ld a, [wRLEByteCount]
+ inc a ; include sentinel in counting
+ ret
+
+; sets movement byte 1 for sprite [$FF8C] to $FE and byte 2 to [$FF8D]
+SetSpriteMovementBytesToFE:: ; 3533 (0:3533)
+ push hl
+ call GetSpriteMovementByte1Pointer
+ ld [hl], $fe
+ call GetSpriteMovementByte2Pointer
+ ld a, [$ff8d]
+ ld [hl], a
+ pop hl
+ ret
+
+; sets both movement bytes for sprite [$FF8C] to $FF
+SetSpriteMovementBytesToFF:: ; 3541 (0:3541)
+ push hl
+ call GetSpriteMovementByte1Pointer
+ ld [hl],$FF
+ call GetSpriteMovementByte2Pointer
+ ld [hl],$FF ; prevent person from walking?
+ pop hl
+ ret
+
+; returns the sprite movement byte 1 pointer for sprite [$FF8C] in hl
+GetSpriteMovementByte1Pointer:: ; 354e (0:354e)
+ ld h,$C2
+ ld a,[H_SPRITEINDEX] ; the sprite to move
+ swap a
+ add a,6
+ ld l,a
+ ret
+
+; returns the sprite movement byte 2 pointer for sprite [$FF8C] in hl
+GetSpriteMovementByte2Pointer:: ; 3558 (0:3558)
+ push de
+ ld hl,W_MAPSPRITEDATA
+ ld a,[$FF8C] ; the sprite to move
+ dec a
+ add a
+ ld d,0
+ ld e,a
+ add hl,de
+ pop de
+ ret
+
+GetTrainerInformation:: ; 3566 (0:3566)
+ call GetTrainerName
+ ld a, [wLinkState]
+ and a
+ jr nz, .linkBattle
+ ld a, Bank(TrainerPicAndMoneyPointers)
+ call BankswitchHome
+ ld a, [W_TRAINERCLASS] ; wd031
+ dec a
+ ld hl, TrainerPicAndMoneyPointers
+ ld bc, $5
+ call AddNTimes
+ ld de, wTrainerPicPointer
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hli]
+ ld [de], a
+ ld de, wd046
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hli]
+ ld [de], a
+ jp BankswitchBack
+.linkBattle
+ ld hl, wTrainerPicPointer
+ ld de, RedPicFront
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ ret
+
+GetTrainerName:: ; 359e (0:359e)
+ ld b, BANK(GetTrainerName_)
+ ld hl, GetTrainerName_
+ jp Bankswitch
+
+
+HasEnoughMoney::
+; Check if the player has at least as much
+; money as the 3-byte BCD value at $ff9f.
+ ld de, wPlayerMoney
+ ld hl, $ff9f
+ ld c, 3
+ jp StringCmp
+
+HasEnoughCoins::
+; Check if the player has at least as many
+; coins as the 2-byte BCD value at $ffa0.
+ ld de, wPlayerCoins
+ ld hl, $ffa0
+ ld c, 2
+ jp StringCmp
+
+
+BankswitchHome:: ; 35d9 (0:35d9)
+; switches to bank # in a
+; Only use this when in the home bank!
+ ld [wcf09],a
+ ld a,[H_LOADEDROMBANK]
+ ld [wcf08],a
+ ld a,[wcf09]
+ call BankswitchCommon
+ ret
+
+BankswitchBack:: ; 35e8 (0:35e8)
+; returns from BankswitchHome
+ ld a,[wcf08]
+ call BankswitchCommon
+ ret
+
+BankswitchCommon:: ; 3e7e (0:3e7e)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+Bankswitch:: ; 3e84 (0:3e84)
+; self-contained bankswitch, use this when not in the home bank
+; switches to the bank in b
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,b
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call .jumptoaddress
+ pop bc
+ ld a,b
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+.jumptoaddress
+ jp [hl]
+
+; displays yes/no choice
+; yes -> set carry
+YesNoChoice:: ; 35ec (0:35ec)
+ call SaveScreenTilesToBuffer1
+ call InitYesNoTextBoxParameters
+ jr DisplayYesNoChoice
+
+Func_35f4:: ; 35f4 (0:35f4)
+ ld a, TWO_OPTION_MENU
+ ld [wTextBoxID], a
+ call InitYesNoTextBoxParameters
+ jp DisplayTextBoxID
+
+InitYesNoTextBoxParameters:: ; 35ff (0:35ff)
+ xor a ; YES_NO_MENU
+ ld [wTwoOptionMenuID], a
+ hlCoord 14, 7
+ ld bc, $80f
+ ret
+
+YesNoChoicePokeCenter:: ; 360a (0:360a)
+ call SaveScreenTilesToBuffer1
+ ld a, HEAL_CANCEL_MENU
+ ld [wTwoOptionMenuID], a
+ hlCoord 11, 6
+ ld bc, $80c
+ jr DisplayYesNoChoice
+
+Func_361a:: ; 361a (0:361a)
+ call SaveScreenTilesToBuffer1
+ ld a, WIDE_YES_NO_MENU
+ ld [wTwoOptionMenuID], a
+ hlCoord 12, 7
+ ld bc, $080d
+DisplayYesNoChoice:: ; 3628 (0:3628)
+ ld a, TWO_OPTION_MENU
+ ld [wTextBoxID], a
+ call DisplayTextBoxID
+ jp LoadScreenTilesFromBuffer1
+
+; calculates the difference |a-b|, setting carry flag if a<b
+CalcDifference:: ; 3633 (0:3633)
+ sub b
+ ret nc
+ cpl
+ add $1
+ scf
+ ret
+
+MoveSprite:: ; 363a (0:363a)
+; move the sprite [$FF8C] with the movement pointed to by de
+; actually only copies the movement data to wcc5b for later
+ call SetSpriteMovementBytesToFF
+MoveSprite_:: ; 363d (0:363d)
+ push hl
+ push bc
+ call GetSpriteMovementByte1Pointer
+ xor a
+ ld [hl],a
+ ld hl,wcc5b
+ ld c,0
+
+.loop
+ ld a,[de]
+ ld [hli],a
+ inc de
+ inc c
+ cp a,$FF ; have we reached the end of the movement data?
+ jr nz,.loop
+
+ ld a,c
+ ld [wcf0f],a ; number of steps taken
+
+ pop bc
+ ld hl,wd730
+ set 0,[hl]
+ pop hl
+ xor a
+ ld [wOverrideSimulatedJoypadStatesMask],a
+ ld [wSimulatedJoypadStatesEnd],a
+ dec a
+ ld [wJoyIgnore],a
+ ld [wWastedByteCD3A],a
+ ret
+
+; divides [$ffe5] by [$ffe6] and stores the quotient in [$ffe7]
+DivideBytes:: ; 366b (0:366b)
+ push hl
+ ld hl, $ffe7
+ xor a
+ ld [hld], a
+ ld a, [hld]
+ and a
+ jr z, .done
+ ld a, [hli]
+.loop
+ sub [hl]
+ jr c, .done
+ inc hl
+ inc [hl]
+ dec hl
+ jr .loop
+.done
+ pop hl
+ ret
+
+
+LoadFontTilePatterns::
+ ld a, [rLCDC]
+ bit 7, a ; is the LCD enabled?
+ jr nz, .on
+.off
+ ld hl, FontGraphics
+ ld de, vFont
+ ld bc, $400
+ ld a, BANK(FontGraphics)
+ jp FarCopyDataDouble ; if LCD is off, transfer all at once
+.on
+ ld de, FontGraphics
+ ld hl, vFont
+ ld bc, BANK(FontGraphics) << 8 | $80
+ jp CopyVideoDataDouble ; if LCD is on, transfer during V-blank
+
+LoadTextBoxTilePatterns::
+ ld a, [rLCDC]
+ bit 7, a ; is the LCD enabled?
+ jr nz, .on
+.off
+ ld hl, TextBoxGraphics
+ ld de, vChars2 + $600
+ ld bc, $200
+ ld a, BANK(TextBoxGraphics)
+ jp FarCopyData2 ; if LCD is off, transfer all at once
+.on
+ ld de, TextBoxGraphics
+ ld hl, vChars2 + $600
+ ld bc, BANK(TextBoxGraphics) << 8 | $20
+ jp CopyVideoData ; if LCD is on, transfer during V-blank
+
+LoadHpBarAndStatusTilePatterns::
+ ld a, [rLCDC]
+ bit 7, a ; is the LCD enabled?
+ jr nz, .on
+.off
+ ld hl, HpBarAndStatusGraphics
+ ld de, vChars2 + $620
+ ld bc, $1e0
+ ld a, BANK(HpBarAndStatusGraphics)
+ jp FarCopyData2 ; if LCD is off, transfer all at once
+.on
+ ld de, HpBarAndStatusGraphics
+ ld hl, vChars2 + $620
+ ld bc, BANK(HpBarAndStatusGraphics) << 8 | $1e
+ jp CopyVideoData ; if LCD is on, transfer during V-blank
+
+
+UncompressSpriteFromDE:: ; 36eb (0:36eb)
+; Decompress pic at a:de.
+ ld hl, W_SPRITEINPUTPTR
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ jp UncompressSpriteData
+
+
+SaveScreenTilesToBuffer2:: ; 36f4 (0:36f4)
+ ld hl, wTileMap
+ ld de, wTileMapBackup2
+ ld bc, $168
+ call CopyData
+ ret
+
+LoadScreenTilesFromBuffer2:: ; 3701 (0:3701)
+ call LoadScreenTilesFromBuffer2DisableBGTransfer
+ ld a, $1
+ ld [H_AUTOBGTRANSFERENABLED], a ; $ffba
+ ret
+
+; loads screen tiles stored in wTileMapBackup2 but leaves H_AUTOBGTRANSFERENABLED disabled
+LoadScreenTilesFromBuffer2DisableBGTransfer:: ; 3709 (0:3709)
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a ; $ffba
+ ld hl, wTileMapBackup2
+ ld de, wTileMap
+ ld bc, $168
+ call CopyData
+ ret
+
+SaveScreenTilesToBuffer1:: ; 3719 (0:3719)
+ ld hl, wTileMap
+ ld de, wTileMapBackup
+ ld bc, $168
+ jp CopyData
+
+LoadScreenTilesFromBuffer1:: ; 3725 (0:3725)
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a ; $ffba
+ ld hl, wTileMapBackup
+ ld de, wTileMap
+ ld bc, $168
+ call CopyData
+ ld a, $1
+ ld [H_AUTOBGTRANSFERENABLED], a ; $ffba
+ ret
+
+DelayFrames:: ; 3739 (0:3739)
+; wait n frames, where n is the value in c
+ call DelayFrame
+ dec c
+ jr nz,DelayFrames
+ ret
+
+PlaySoundWaitForCurrent:: ; 3740 (0:3740)
+ push af
+ call WaitForSoundToFinish
+ pop af
+ jp PlaySound
+
+; Wait for sound to finish playing
+WaitForSoundToFinish:: ; 3748 (0:3748)
+ ld a, [wLowHealthAlarm]
+ and $80
+ ret nz
+ push hl
+.asm_374f
+ ld hl, wc02a
+ xor a
+ or [hl]
+ inc hl
+ or [hl]
+ inc hl
+ inc hl
+ or [hl]
+ jr nz, .asm_374f
+ pop hl
+ ret
+
+NamePointers:: ; 375d (0:375d)
+ dw MonsterNames
+ dw MoveNames
+ dw UnusedNames
+ dw ItemNames
+ dw wPartyMonOT ; player's OT names list
+ dw wEnemyMonOT ; enemy's OT names list
+ dw TrainerNames
+
+GetName:: ; 376b (0:376b)
+; arguments:
+; [wd0b5] = which name
+; [wNameListType] = which list
+; [wPredefBank] = bank of list
+;
+; returns pointer to name in de
+ ld a,[wd0b5]
+ ld [wd11e],a
+
+ ; TM names are separate from item names.
+ ; BUG: This applies to all names instead of just items.
+ cp HM_01
+ jp nc, GetMachineName
+
+ ld a,[H_LOADEDROMBANK]
+ push af
+ push hl
+ push bc
+ push de
+ ld a,[wNameListType] ;List3759_entrySelector
+ dec a
+ jr nz,.otherEntries
+ ;1 = MON_NAMES
+ call GetMonName
+ ld hl,11
+ add hl,de
+ ld e,l
+ ld d,h
+ jr .gotPtr
+.otherEntries ; $378d
+ ;2-7 = OTHER ENTRIES
+ ld a,[wPredefBank]
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ld a,[wNameListType] ;VariousNames' entryID
+ dec a
+ add a
+ ld d,0
+ ld e,a
+ jr nc,.skip
+ inc d
+.skip ; $37a0
+ ld hl,NamePointers
+ add hl,de
+ ld a,[hli]
+ ld [$ff96],a
+ ld a,[hl]
+ ld [$ff95],a
+ ld a,[$ff95]
+ ld h,a
+ ld a,[$ff96]
+ ld l,a
+ ld a,[wd0b5]
+ ld b,a
+ ld c,0
+.nextName
+ ld d,h
+ ld e,l
+.nextChar
+ ld a,[hli]
+ cp a, "@"
+ jr nz,.nextChar
+ inc c ;entry counter
+ ld a,b ;wanted entry
+ cp c
+ jr nz,.nextName
+ ld h,d
+ ld l,e
+ ld de,wcd6d
+ ld bc,$0014
+ call CopyData
+.gotPtr ; $37cd
+ ld a,e
+ ld [wcf8d],a
+ ld a,d
+ ld [wcf8e],a
+ pop de
+ pop bc
+ pop hl
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+GetItemPrice:: ; 37df (0:37df)
+; Stores item's price as BCD at hItemPrice (3 bytes)
+; Input: [wcf91] = item id
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, [wListMenuID]
+ cp MOVESLISTMENU
+ ld a, BANK(ItemPrices)
+ jr nz, .asm_37ed
+ ld a, $f ; hardcoded Bank
+.asm_37ed
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ld hl, wItemPrices
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wcf91] ; a contains item id
+ cp HM_01
+ jr nc, .getTMPrice
+ ld bc, $3
+.asm_3802
+ add hl, bc
+ dec a
+ jr nz, .asm_3802
+ dec hl
+ ld a, [hld]
+ ld [hItemPrice + 2], a
+ ld a, [hld]
+ ld [hItemPrice + 1], a
+ ld a, [hl]
+ ld [hItemPrice], a
+ jr .asm_381c
+.getTMPrice
+ ld a, Bank(GetMachinePrice)
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ call GetMachinePrice
+.asm_381c
+ ld de, hItemPrice
+ pop af
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+
+; copies a string from [de] to [wcf4b]
+CopyStringToCF4B:: ; 3826 (0:3826)
+ ld hl, wcf4b
+ ; fall through
+
+; copies a string from [de] to [hl]
+CopyString:: ; 3829 (0:3829)
+ ld a, [de]
+ inc de
+ ld [hli], a
+ cp "@"
+ jr nz, CopyString
+ ret
+
+; this function is used when lower button sensitivity is wanted (e.g. menus)
+; OUTPUT: [hJoy5] = pressed buttons in usual format
+; there are two flags that control its functionality, [hJoy6] and [hJoy7]
+; there are esentially three modes of operation
+; 1. Get newly pressed buttons only
+; ([hJoy7] == 0, [hJoy6] == any)
+; Just copies [hJoyPressed] to [hJoy5].
+; 2. Get currently pressed buttons at low sample rate with delay
+; ([hJoy7] == 1, [hJoy6] != 0)
+; If the user holds down buttons for more than half a second,
+; report buttons as being pressed up to 12 times per second thereafter.
+; If the user holds down buttons for less than half a second,
+; report only one button press.
+; 3. Same as 2, but report no buttons as pressed if A or B is held down.
+; ([hJoy7] == 1, [hJoy6] == 0)
+JoypadLowSensitivity:: ; 3831 (0:3831)
+ call Joypad
+ ld a,[hJoy7] ; flag
+ and a ; get all currently pressed buttons or only newly pressed buttons?
+ ld a,[hJoyPressed] ; newly pressed buttons
+ jr z,.storeButtonState
+ ld a,[hJoyHeld] ; all currently pressed buttons
+.storeButtonState
+ ld [hJoy5],a
+ ld a,[hJoyPressed] ; newly pressed buttons
+ and a ; have any buttons been newly pressed since last check?
+ jr z,.noNewlyPressedButtons
+.newlyPressedButtons
+ ld a,30 ; half a second delay
+ ld [H_FRAMECOUNTER],a
+ ret
+.noNewlyPressedButtons
+ ld a,[H_FRAMECOUNTER]
+ and a ; is the delay over?
+ jr z,.delayOver
+.delayNotOver
+ xor a
+ ld [hJoy5],a ; report no buttons as pressed
+ ret
+.delayOver
+; if [hJoy6] = 0 and A or B is pressed, report no buttons as pressed
+ ld a,[hJoyHeld]
+ and A_BUTTON | B_BUTTON
+ jr z,.setShortDelay
+ ld a,[hJoy6] ; flag
+ and a
+ jr nz,.setShortDelay
+ xor a
+ ld [hJoy5],a
+.setShortDelay
+ ld a,5 ; 1/12 of a second delay
+ ld [H_FRAMECOUNTER],a
+ ret
+
+WaitForTextScrollButtonPress:: ; 3865 (0:3865)
+ ld a, [H_DOWNARROWBLINKCNT1]
+ push af
+ ld a, [H_DOWNARROWBLINKCNT2]
+ push af
+ xor a
+ ld [H_DOWNARROWBLINKCNT1], a
+ ld a, $6
+ ld [H_DOWNARROWBLINKCNT2], a
+.loop
+ push hl
+ ld a, [wTownMapSpriteBlinkingEnabled]
+ and a
+ jr z, .skipAnimation
+ call TownMapSpriteBlinkingAnimation
+.skipAnimation
+ hlCoord 18, 16
+ call HandleDownArrowBlinkTiming
+ pop hl
+ call JoypadLowSensitivity
+ predef CableClub_Run
+ ld a, [hJoy5]
+ and A_BUTTON | B_BUTTON
+ jr z, .loop
+ pop af
+ ld [H_DOWNARROWBLINKCNT2], a
+ pop af
+ ld [H_DOWNARROWBLINKCNT1], a
+ ret
+
+; (unless in link battle) waits for A or B being pressed and outputs the scrolling sound effect
+ManualTextScroll:: ; 3898 (0:3898)
+ ld a, [wLinkState]
+ cp LINK_STATE_BATTLING
+ jr z, .inLinkBattle
+ call WaitForTextScrollButtonPress
+ ld a, (SFX_02_40 - SFX_Headers_02) / 3
+ jp PlaySound
+.inLinkBattle
+ ld c, $41
+ jp DelayFrames
+
+; function to do multiplication
+; all values are big endian
+; INPUT
+; FF96-FF98 = multiplicand
+; FF99 = multiplier
+; OUTPUT
+; FF95-FF98 = product
+Multiply:: ; 38ac (0:38ac)
+ push hl
+ push bc
+ callab _Multiply
+ pop bc
+ pop hl
+ ret
+
+; function to do division
+; all values are big endian
+; INPUT
+; FF95-FF98 = dividend
+; FF99 = divisor
+; b = number of bytes in the dividend (starting from FF95)
+; OUTPUT
+; FF95-FF98 = quotient
+; FF99 = remainder
+Divide:: ; 38b9 (0:38b9)
+ push hl
+ push de
+ push bc
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,Bank(_Divide)
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ call _Divide
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; This function is used to wait a short period after printing a letter to the
+; screen unless the player presses the A/B button or the delay is turned off
+; through the [wd730] or [wd358] flags.
+PrintLetterDelay:: ; 38d3 (0:38d3)
+ ld a,[wd730]
+ bit 6,a
+ ret nz
+ ld a,[wd358]
+ bit 1,a
+ ret z
+ push hl
+ push de
+ push bc
+ ld a,[wd358]
+ bit 0,a
+ jr z,.waitOneFrame
+ ld a,[W_OPTIONS]
+ and $f
+ ld [H_FRAMECOUNTER],a
+ jr .checkButtons
+.waitOneFrame
+ ld a,1
+ ld [H_FRAMECOUNTER],a
+.checkButtons
+ call Joypad
+ ld a,[hJoyHeld]
+.checkAButton
+ bit 0,a ; is the A button pressed?
+ jr z,.checkBButton
+ jr .endWait
+.checkBButton
+ bit 1,a ; is the B button pressed?
+ jr z,.buttonsNotPressed
+.endWait
+ call DelayFrame
+ jr .done
+.buttonsNotPressed ; if neither A nor B is pressed
+ ld a,[H_FRAMECOUNTER]
+ and a
+ jr nz,.checkButtons
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; Copies [hl, bc) to [de, bc - hl).
+; In other words, the source data is from hl up to but not including bc,
+; and the destination is de.
+CopyDataUntil:: ; 3913 (0:3913)
+ ld a,[hli]
+ ld [de],a
+ inc de
+ ld a,h
+ cp b
+ jr nz,CopyDataUntil
+ ld a,l
+ cp c
+ jr nz,CopyDataUntil
+ ret
+
+; Function to remove a pokemon from the party or the current box.
+; wWhichPokemon determines the pokemon.
+; [wcf95] == 0 specifies the party.
+; [wcf95] != 0 specifies the current box.
+RemovePokemon:: ; 391f (0:391f)
+ ld hl, _RemovePokemon
+ ld b, BANK(_RemovePokemon)
+ jp Bankswitch
+
+AddPartyMon:: ; 3927 (0:3927)
+ push hl
+ push de
+ push bc
+ callba _AddPartyMon
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; calculates all 5 stats of current mon and writes them to [de]
+CalcStats:: ; 3936 (0:3936)
+ ld c, $0
+.statsLoop
+ inc c
+ call CalcStat
+ ld a, [H_MULTIPLICAND+1]
+ ld [de], a
+ inc de
+ ld a, [H_MULTIPLICAND+2]
+ ld [de], a
+ inc de
+ ld a, c
+ cp $5
+ jr nz, .statsLoop
+ ret
+
+; calculates stat c of current mon
+; c: stat to calc (HP=1,Atk=2,Def=3,Spd=4,Spc=5)
+; b: consider stat exp?
+; hl: base ptr to stat exp values ([hl + 2*c - 1] and [hl + 2*c])
+CalcStat:: ; 394a (0:394a)
+ push hl
+ push de
+ push bc
+ ld a, b
+ ld d, a
+ push hl
+ ld hl, W_MONHEADER
+ ld b, $0
+ add hl, bc
+ ld a, [hl] ; read base value of stat
+ ld e, a
+ pop hl
+ push hl
+ sla c
+ ld a, d
+ and a
+ jr z, .statExpDone ; consider stat exp?
+ add hl, bc ; skip to corresponding stat exp value
+.statExpLoop ; calculates ceil(Sqrt(stat exp)) in b
+ xor a
+ ld [H_MULTIPLICAND], a
+ ld [H_MULTIPLICAND+1], a
+ inc b ; increment current stat exp bonus
+ ld a, b
+ cp $ff
+ jr z, .statExpDone
+ ld [H_MULTIPLICAND+2], a
+ ld [H_MULTIPLIER], a
+ call Multiply
+ ld a, [hld]
+ ld d, a
+ ld a, [$ff98]
+ sub d
+ ld a, [hli]
+ ld d, a
+ ld a, [$ff97]
+ sbc d ; test if (current stat exp bonus)^2 < stat exp
+ jr c, .statExpLoop
+.statExpDone
+ srl c
+ pop hl
+ push bc
+ ld bc, $b ; skip to stat IV values
+ add hl, bc
+ pop bc
+ ld a, c
+ cp $2
+ jr z, .getAttackIV
+ cp $3
+ jr z, .getDefenseIV
+ cp $4
+ jr z, .getSpeedIV
+ cp $5
+ jr z, .getSpecialIV
+.getHpIV
+ push bc
+ ld a, [hl] ; Atk IV
+ swap a
+ and $1
+ sla a
+ sla a
+ sla a
+ ld b, a
+ ld a, [hli] ; Def IV
+ and $1
+ sla a
+ sla a
+ add b
+ ld b, a
+ ld a, [hl] ; Spd IV
+ swap a
+ and $1
+ sla a
+ add b
+ ld b, a
+ ld a, [hl] ; Spc IV
+ and $1
+ add b ; HP IV: LSB of the other 4 IVs
+ pop bc
+ jr .calcStatFromIV
+.getAttackIV
+ ld a, [hl]
+ swap a
+ and $f
+ jr .calcStatFromIV
+.getDefenseIV
+ ld a, [hl]
+ and $f
+ jr .calcStatFromIV
+.getSpeedIV
+ inc hl
+ ld a, [hl]
+ swap a
+ and $f
+ jr .calcStatFromIV
+.getSpecialIV
+ inc hl
+ ld a, [hl]
+ and $f
+.calcStatFromIV
+ ld d, $0
+ add e
+ ld e, a
+ jr nc, .noCarry
+ inc d ; de = Base + IV
+.noCarry
+ sla e
+ rl d ; de = (Base + IV) * 2
+ srl b
+ srl b ; b = ceil(Sqrt(stat exp)) / 4
+ ld a, b
+ add e
+ jr nc, .noCarry2
+ inc d ; da = (Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4
+.noCarry2
+ ld [H_MULTIPLICAND+2], a
+ ld a, d
+ ld [H_MULTIPLICAND+1], a
+ xor a
+ ld [H_MULTIPLICAND], a
+ ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL
+ ld [H_MULTIPLIER], a
+ call Multiply ; ((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level
+ ld a, [H_MULTIPLICAND]
+ ld [H_DIVIDEND], a
+ ld a, [H_MULTIPLICAND+1]
+ ld [H_DIVIDEND+1], a
+ ld a, [H_MULTIPLICAND+2]
+ ld [H_DIVIDEND+2], a
+ ld a, $64
+ ld [H_DIVISOR], a
+ ld a, $3
+ ld b, a
+ call Divide ; (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100
+ ld a, c
+ cp $1
+ ld a, $5
+ jr nz, .notHPStat
+ ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL
+ ld b, a
+ ld a, [H_MULTIPLICAND+2]
+ add b
+ ld [H_MULTIPLICAND+2], a
+ jr nc, .noCarry3
+ ld a, [H_MULTIPLICAND+1]
+ inc a
+ ld [H_MULTIPLICAND+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level
+.noCarry3
+ ld a, $a
+.notHPStat
+ ld b, a
+ ld a, [H_MULTIPLICAND+2]
+ add b
+ ld [H_MULTIPLICAND+2], a
+ jr nc, .noCarry4
+ ld a, [H_MULTIPLICAND+1]
+ inc a ; non-HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + 5
+ ld [H_MULTIPLICAND+1], a ; HP: (((Base + IV) * 2 + ceil(Sqrt(stat exp)) / 4) * Level) / 100 + Level + 10
+.noCarry4
+ ld a, [H_MULTIPLICAND+1] ; check for overflow (>999)
+ cp $4
+ jr nc, .overflow
+ cp $3
+ jr c, .noOverflow
+ ld a, [H_MULTIPLICAND+2]
+ cp $e8
+ jr c, .noOverflow
+.overflow
+ ld a, $3 ; overflow: cap at 999
+ ld [H_MULTIPLICAND+1], a
+ ld a, $e7
+ ld [H_MULTIPLICAND+2], a
+.noOverflow
+ pop bc
+ pop de
+ pop hl
+ ret
+
+AddEnemyMonToPlayerParty:: ; 3a53 (0:3a53)
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, BANK(_AddEnemyMonToPlayerParty)
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ call _AddEnemyMonToPlayerParty
+ pop bc
+ ld a, b
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+
+Func_3a68:: ; 3a68 (0:3a68)
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, BANK(Func_f51e)
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ call Func_f51e
+ pop bc
+ ld a, b
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ ret
+
+; skips a text entries, each of size $b (like trainer name, OT name, rival name, ...)
+; hl: base pointer, will be incremented by $b * a
+SkipFixedLengthTextEntries:: ; 3a7d (0:3a7d)
+ and a
+ ret z
+ ld bc, $b
+.skipLoop
+ add hl, bc
+ dec a
+ jr nz, .skipLoop
+ ret
+
+AddNTimes:: ; 3a87 (0:3a87)
+; add bc to hl a times
+ and a
+ ret z
+.loop
+ add hl,bc
+ dec a
+ jr nz,.loop
+ ret
+
+; Compare strings, c bytes in length, at de and hl.
+; Often used to compare big endian numbers in battle calculations.
+StringCmp:: ; 3a8e (0:3a8e)
+ ld a,[de]
+ cp [hl]
+ ret nz
+ inc de
+ inc hl
+ dec c
+ jr nz,StringCmp
+ ret
+
+; INPUT:
+; a = oam block index (each block is 4 oam entries)
+; b = Y coordinate of upper left corner of sprite
+; c = X coordinate of upper left corner of sprite
+; de = base address of 4 tile number and attribute pairs
+WriteOAMBlock:: ; 3a97 (0:3a97)
+ ld h,wOAMBuffer / $100
+ swap a ; multiply by 16
+ ld l,a
+ call .writeOneEntry ; upper left
+ push bc
+ ld a,8
+ add c
+ ld c,a
+ call .writeOneEntry ; upper right
+ pop bc
+ ld a,8
+ add b
+ ld b,a
+ call .writeOneEntry ; lower left
+ ld a,8
+ add c
+ ld c,a
+ ; lower right
+.writeOneEntry
+ ld [hl],b ; Y coordinate
+ inc hl
+ ld [hl],c ; X coordinate
+ inc hl
+ ld a,[de] ; tile number
+ inc de
+ ld [hli],a
+ ld a,[de] ; attribute
+ inc de
+ ld [hli],a
+ ret
+
+HandleMenuInput:: ; 3abe (0:3abe)
+ xor a
+ ld [wd09b],a
+
+HandleMenuInputPokemonSelection:: ; 3ac2 (0:3ac2)
+ ld a,[H_DOWNARROWBLINKCNT1]
+ push af
+ ld a,[H_DOWNARROWBLINKCNT2]
+ push af ; save existing values on stack
+ xor a
+ ld [H_DOWNARROWBLINKCNT1],a ; blinking down arrow timing value 1
+ ld a,$06
+ ld [H_DOWNARROWBLINKCNT2],a ; blinking down arrow timing value 2
+.loop1
+ xor a
+ ld [wPartyMonAnimCounter],a ; counter for pokemon shaking animation
+ call PlaceMenuCursor
+ call Delay3
+.loop2
+ push hl
+ ld a,[wd09b]
+ and a ; is it a pokemon selection menu?
+ jr z,.getJoypadState
+ callba AnimatePartyMon ; shake mini sprite of selected pokemon
+.getJoypadState
+ pop hl
+ call JoypadLowSensitivity
+ ld a,[hJoy5]
+ and a ; was a key pressed?
+ jr nz,.keyPressed
+ push hl
+ hlCoord 18, 11 ; coordinates of blinking down arrow in some menus
+ call HandleDownArrowBlinkTiming ; blink down arrow (if any)
+ pop hl
+ ld a,[wMenuJoypadPollCount]
+ dec a
+ jr z,.giveUpWaiting
+ jr .loop2
+.giveUpWaiting
+; if a key wasn't pressed within the specified number of checks
+ pop af
+ ld [H_DOWNARROWBLINKCNT2],a
+ pop af
+ ld [H_DOWNARROWBLINKCNT1],a ; restore previous values
+ xor a
+ ld [wMenuWrappingEnabled],a ; disable menu wrapping
+ ret
+.keyPressed
+ xor a
+ ld [wcc4b],a
+ ld a,[hJoy5]
+ ld b,a
+ bit 6,a ; pressed Up key?
+ jr z,.checkIfDownPressed
+.upPressed
+ ld a,[wCurrentMenuItem] ; selected menu item
+ and a ; already at the top of the menu?
+ jr z,.alreadyAtTop
+.notAtTop
+ dec a
+ ld [wCurrentMenuItem],a ; move selected menu item up one space
+ jr .checkOtherKeys
+.alreadyAtTop
+ ld a,[wMenuWrappingEnabled]
+ and a ; is wrapping around enabled?
+ jr z,.noWrappingAround
+ ld a,[wMaxMenuItem]
+ ld [wCurrentMenuItem],a ; wrap to the bottom of the menu
+ jr .checkOtherKeys
+.checkIfDownPressed
+ bit 7,a
+ jr z,.checkOtherKeys
+.downPressed
+ ld a,[wCurrentMenuItem]
+ inc a
+ ld c,a
+ ld a,[wMaxMenuItem]
+ cp c
+ jr nc,.notAtBottom
+.alreadyAtBottom
+ ld a,[wMenuWrappingEnabled]
+ and a ; is wrapping around enabled?
+ jr z,.noWrappingAround
+ ld c,$00 ; wrap from bottom to top
+.notAtBottom
+ ld a,c
+ ld [wCurrentMenuItem],a
+.checkOtherKeys
+ ld a,[wMenuWatchedKeys]
+ and b ; does the menu care about any of the pressed keys?
+ jp z,.loop1
+.checkIfAButtonOrBButtonPressed
+ ld a,[hJoy5]
+ and A_BUTTON | B_BUTTON
+ jr z,.skipPlayingSound
+.AButtonOrBButtonPressed
+ push hl
+ ld hl,wFlags_0xcd60
+ bit 5,[hl]
+ pop hl
+ jr nz,.skipPlayingSound
+ ld a,(SFX_02_40 - SFX_Headers_02) / 3
+ call PlaySound ; play sound
+.skipPlayingSound
+ pop af
+ ld [H_DOWNARROWBLINKCNT2],a
+ pop af
+ ld [H_DOWNARROWBLINKCNT1],a ; restore previous values
+ xor a
+ ld [wMenuWrappingEnabled],a ; disable menu wrapping
+ ld a,[hJoy5]
+ ret
+.noWrappingAround
+ ld a,[wcc37]
+ and a ; should we return if the user tried to go past the top or bottom?
+ jr z,.checkOtherKeys
+ jr .checkIfAButtonOrBButtonPressed
+
+PlaceMenuCursor:: ; 3b7c (0:3b7c)
+ ld a,[wTopMenuItemY]
+ and a ; is the y coordinate 0?
+ jr z,.adjustForXCoord
+ ld hl,wTileMap
+ ld bc,SCREEN_WIDTH
+.topMenuItemLoop
+ add hl,bc
+ dec a
+ jr nz,.topMenuItemLoop
+.adjustForXCoord
+ ld a,[wTopMenuItemX]
+ ld b,0
+ ld c,a
+ add hl,bc
+ push hl
+ ld a,[wLastMenuItem]
+ and a ; was the previous menu id 0?
+ jr z,.checkForArrow1
+ push af
+ ld a,[hFlags_0xFFF6]
+ bit 1,a ; is the menu double spaced?
+ jr z,.doubleSpaced1
+ ld bc,20
+ jr .getOldMenuItemScreenPosition
+.doubleSpaced1
+ ld bc,40
+.getOldMenuItemScreenPosition
+ pop af
+.oldMenuItemLoop
+ add hl,bc
+ dec a
+ jr nz,.oldMenuItemLoop
+.checkForArrow1
+ ld a,[hl]
+ cp a,"▶" ; was an arrow next to the previously selected menu item?
+ jr nz,.skipClearingArrow
+.clearArrow
+ ld a,[wTileBehindCursor]
+ ld [hl],a
+.skipClearingArrow
+ pop hl
+ ld a,[wCurrentMenuItem]
+ and a
+ jr z,.checkForArrow2
+ push af
+ ld a,[hFlags_0xFFF6]
+ bit 1,a ; is the menu double spaced?
+ jr z,.doubleSpaced2
+ ld bc,20
+ jr .getCurrentMenuItemScreenPosition
+.doubleSpaced2
+ ld bc,40
+.getCurrentMenuItemScreenPosition
+ pop af
+.currentMenuItemLoop
+ add hl,bc
+ dec a
+ jr nz,.currentMenuItemLoop
+.checkForArrow2
+ ld a,[hl]
+ cp a,"▶" ; has the right arrow already been placed?
+ jr z,.skipSavingTile ; if so, don't lose the saved tile
+ ld [wTileBehindCursor],a ; save tile before overwriting with right arrow
+.skipSavingTile
+ ld a,"▶" ; place right arrow
+ ld [hl],a
+ ld a,l
+ ld [wMenuCursorLocation],a
+ ld a,h
+ ld [wMenuCursorLocation + 1],a
+ ld a,[wCurrentMenuItem]
+ ld [wLastMenuItem],a
+ ret
+
+; This is used to mark a menu cursor other than the one currently being
+; manipulated. In the case of submenus, this is used to show the location of
+; the menu cursor in the parent menu. In the case of swapping items in list,
+; this is used to mark the item that was first chosen to be swapped.
+PlaceUnfilledArrowMenuCursor:: ; 3bec (0:3bec)
+ ld b,a
+ ld a,[wMenuCursorLocation]
+ ld l,a
+ ld a,[wMenuCursorLocation + 1]
+ ld h,a
+ ld [hl],$ec ; outline of right arrow
+ ld a,b
+ ret
+
+; Replaces the menu cursor with a blank space.
+EraseMenuCursor:: ; 3bf9 (0:3bf9)
+ ld a,[wMenuCursorLocation]
+ ld l,a
+ ld a,[wMenuCursorLocation + 1]
+ ld h,a
+ ld [hl]," "
+ ret
+
+; This toggles a blinking down arrow at hl on and off after a delay has passed.
+; This is often called even when no blinking is occurring.
+; The reason is that most functions that call this initialize H_DOWNARROWBLINKCNT1 to 0.
+; The effect is that if the tile at hl is initialized with a down arrow,
+; this function will toggle that down arrow on and off, but if the tile isn't
+; initliazed with a down arrow, this function does nothing.
+; That allows this to be called without worrying about if a down arrow should
+; be blinking.
+HandleDownArrowBlinkTiming:: ; 3c04 (0:3c04)
+ ld a,[hl]
+ ld b,a
+ ld a,$ee ; down arrow
+ cp b
+ jr nz,.downArrowOff
+.downArrowOn
+ ld a,[H_DOWNARROWBLINKCNT1]
+ dec a
+ ld [H_DOWNARROWBLINKCNT1],a
+ ret nz
+ ld a,[H_DOWNARROWBLINKCNT2]
+ dec a
+ ld [H_DOWNARROWBLINKCNT2],a
+ ret nz
+ ld a," "
+ ld [hl],a
+ ld a,$ff
+ ld [H_DOWNARROWBLINKCNT1],a
+ ld a,$06
+ ld [H_DOWNARROWBLINKCNT2],a
+ ret
+.downArrowOff
+ ld a,[H_DOWNARROWBLINKCNT1]
+ and a
+ ret z
+ dec a
+ ld [H_DOWNARROWBLINKCNT1],a
+ ret nz
+ dec a
+ ld [H_DOWNARROWBLINKCNT1],a
+ ld a,[H_DOWNARROWBLINKCNT2]
+ dec a
+ ld [H_DOWNARROWBLINKCNT2],a
+ ret nz
+ ld a,$06
+ ld [H_DOWNARROWBLINKCNT2],a
+ ld a,$ee ; down arrow
+ ld [hl],a
+ ret
+
+; The following code either enables or disables the automatic drawing of
+; text boxes by DisplayTextID. Both functions cause DisplayTextID to wait
+; for a button press after displaying text (unless [wcc47] is set).
+
+EnableAutoTextBoxDrawing:: ; 3c3c (0:3c3c)
+ xor a
+ jr AutoTextBoxDrawingCommon
+
+DisableAutoTextBoxDrawing:: ; 3c3f (0:3c3f)
+ ld a,$01
+
+AutoTextBoxDrawingCommon:: ; 3c41 (0:3c41)
+ ld [wAutoTextBoxDrawingControl],a
+ xor a
+ ld [wDoNotWaitForButtonPressAfterDisplayingText],a ; make DisplayTextID wait for button press
+ ret
+
+PrintText:: ; 3c49 (0:3c49)
+; Print text hl at (1, 14).
+ push hl
+ ld a,MESSAGE_BOX
+ ld [wTextBoxID],a
+ call DisplayTextBoxID
+ call UpdateSprites
+ call Delay3
+ pop hl
+Func_3c59:: ; 3c59 (0:3c59)
+ bcCoord 1, 14
+ jp TextCommandProcessor
+
+
+PrintNumber:: ; 3c5f
+; Print the c-digit, b-byte value at de.
+; Allows 2 to 7 digits. For 1-digit numbers, add
+; the value to char "0" instead of calling PrintNumber.
+; Flags LEADING_ZEROES and LEFT_ALIGN can be given
+; in bits 7 and 6 of b respectively.
+LEADING_ZEROES EQU 7
+LEFT_ALIGN EQU 6
+
+ push bc
+ xor a
+ ld [H_PASTLEADINGZEROES], a
+ ld [H_NUMTOPRINT], a
+ ld [H_NUMTOPRINT + 1], a
+ ld a, b
+ and $f
+ cp 1
+ jr z, .byte
+ cp 2
+ jr z, .word
+.long
+ ld a, [de]
+ ld [H_NUMTOPRINT], a
+ inc de
+ ld a, [de]
+ ld [H_NUMTOPRINT + 1], a
+ inc de
+ ld a, [de]
+ ld [H_NUMTOPRINT + 2], a
+ jr .start
+
+.word
+ ld a, [de]
+ ld [H_NUMTOPRINT + 1], a
+ inc de
+ ld a, [de]
+ ld [H_NUMTOPRINT + 2], a
+ jr .start
+
+.byte
+ ld a, [de]
+ ld [H_NUMTOPRINT + 2], a
+
+.start
+ push de
+
+ ld d, b
+ ld a, c
+ ld b, a
+ xor a
+ ld c, a
+ ld a, b
+
+ cp 2
+ jr z, .tens
+ cp 3
+ jr z, .hundreds
+ cp 4
+ jr z, .thousands
+ cp 5
+ jr z, .ten_thousands
+ cp 6
+ jr z, .hundred_thousands
+
+print_digit: macro
+
+if (\1) / $10000
+ ld a, \1 / $10000 % $100
+else xor a
+endc
+ ld [H_POWEROFTEN + 0], a
+
+if (\1) / $100
+ ld a, \1 / $100 % $100
+else xor a
+endc
+ ld [H_POWEROFTEN + 1], a
+
+ ld a, \1 / $1 % $100
+ ld [H_POWEROFTEN + 2], a
+
+ call .PrintDigit
+ call .NextDigit
+endm
+
+.millions print_digit 1000000
+.hundred_thousands print_digit 100000
+.ten_thousands print_digit 10000
+.thousands print_digit 1000
+.hundreds print_digit 100
+
+.tens
+ ld c, 0
+ ld a, [H_NUMTOPRINT + 2]
+.mod
+ cp 10
+ jr c, .ok
+ sub 10
+ inc c
+ jr .mod
+.ok
+
+ ld b, a
+ ld a, [H_PASTLEADINGZEROES]
+ or c
+ ld [H_PASTLEADINGZEROES], a
+ jr nz, .past
+ call .PrintLeadingZero
+ jr .next
+.past
+ ld a, "0"
+ add c
+ ld [hl], a
+.next
+
+ call .NextDigit
+.ones
+ ld a, "0"
+ add b
+ ld [hli], a
+ pop de
+ dec de
+ pop bc
+ ret
+
+.PrintDigit:
+; Divide by the current decimal place.
+; Print the quotient, and keep the modulus.
+ ld c, 0
+.loop
+ ld a, [H_POWEROFTEN]
+ ld b, a
+ ld a, [H_NUMTOPRINT]
+ ld [H_SAVEDNUMTOPRINT], a
+ cp b
+ jr c, .underflow0
+ sub b
+ ld [H_NUMTOPRINT], a
+ ld a, [H_POWEROFTEN + 1]
+ ld b, a
+ ld a, [H_NUMTOPRINT + 1]
+ ld [H_SAVEDNUMTOPRINT + 1], a
+ cp b
+ jr nc, .noborrow1
+
+ ld a, [H_NUMTOPRINT]
+ or 0
+ jr z, .underflow1
+ dec a
+ ld [H_NUMTOPRINT], a
+ ld a, [H_NUMTOPRINT + 1]
+.noborrow1
+
+ sub b
+ ld [H_NUMTOPRINT + 1], a
+ ld a, [H_POWEROFTEN + 2]
+ ld b, a
+ ld a, [H_NUMTOPRINT + 2]
+ ld [H_SAVEDNUMTOPRINT + 2], a
+ cp b
+ jr nc, .noborrow2
+
+ ld a, [H_NUMTOPRINT + 1]
+ and a
+ jr nz, .borrowed
+
+ ld a, [H_NUMTOPRINT]
+ and a
+ jr z, .underflow2
+ dec a
+ ld [H_NUMTOPRINT], a
+ xor a
+.borrowed
+
+ dec a
+ ld [H_NUMTOPRINT + 1], a
+ ld a, [H_NUMTOPRINT + 2]
+.noborrow2
+ sub b
+ ld [H_NUMTOPRINT + 2], a
+ inc c
+ jr .loop
+
+.underflow2
+ ld a, [H_SAVEDNUMTOPRINT + 1]
+ ld [H_NUMTOPRINT + 1], a
+.underflow1
+ ld a, [H_SAVEDNUMTOPRINT]
+ ld [H_NUMTOPRINT], a
+.underflow0
+ ld a, [H_PASTLEADINGZEROES]
+ or c
+ jr z, .PrintLeadingZero
+
+ ld a, "0"
+ add c
+ ld [hl], a
+ ld [H_PASTLEADINGZEROES], a
+ ret
+
+.PrintLeadingZero:
+ bit LEADING_ZEROES, d
+ ret z
+ ld [hl], "0"
+ ret
+
+.NextDigit:
+; Increment unless the number is left-aligned,
+; leading zeroes are not printed, and no digits
+; have been printed yet.
+ bit LEADING_ZEROES, d
+ jr nz, .inc
+ bit LEFT_ALIGN, d
+ jr z, .inc
+ ld a, [H_PASTLEADINGZEROES]
+ and a
+ ret z
+.inc
+ inc hl
+ ret
+
+
+CallFunctionInTable::
+JumpTable::
+; Call function a in jumptable hl.
+; de is not preserved.
+ push hl
+ push de
+ push bc
+ add a
+ ld d, 0
+ ld e, a
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, .returnAddress
+ push de
+ jp [hl]
+.returnAddress
+ pop bc
+ pop de
+ pop hl
+ ret
+
+
+IsInArray::
+; Search an array at hl for the value in a.
+; Entry size is de bytes.
+; Return count b and carry if found.
+ ld b, 0
+
+IsInRestOfArray::
+ ld c, a
+.loop
+ ld a, [hl]
+ cp -1
+ jr z, .notfound
+ cp c
+ jr z, .found
+ inc b
+ add hl, de
+ jr .loop
+
+.notfound
+ and a
+ ret
+
+.found
+ scf
+ ret
+
+InitMapSprites:: ; 3dba (0:3dba)
+ ld hl, _InitMapSprites ; 1401b (5:401b)
+ ld b,BANK(_InitMapSprites)
+ jp Bankswitch
+
+RestoreScreenTilesAndReloadTilePatterns:: ; 3dbe (0:3dbe)
+ call ClearSprites
+ ld a, $1
+ ld [wUpdateSpritesEnabled], a
+ call ReloadMapSpriteTilePatterns
+ call LoadScreenTilesFromBuffer2
+ call LoadTextBoxTilePatterns
+ call GoPAL_SET_CF1C
+ jr Delay3
+
+
+GBPalWhiteOutWithDelay3::
+ call GBPalWhiteOut
+
+Delay3::
+; The bg map is updated each frame in thirds.
+; Wait three frames to let the bg map fully update.
+ ld c, 3
+ jp DelayFrames
+
+GBPalNormal::
+; Reset BGP and OBP0.
+ ld a, %11100100 ; 3210
+ ld [rBGP], a
+ ld a, %11010000 ; 3100
+ ld [rOBP0], a
+ ret
+
+GBPalWhiteOut::
+; White out all palettes.
+ xor a
+ ld [rBGP],a
+ ld [rOBP0],a
+ ld [rOBP1],a
+ ret
+
+
+GoPAL_SET_CF1C:: ; 3ded (0:3ded)
+ ld b,$ff
+GoPAL_SET:: ; 3def (0:3def)
+ ld a,[wOnSGB]
+ and a
+ ret z
+ predef_jump Func_71ddf
+
+GetHealthBarColor::
+; Return at hl the palette of
+; an HP bar e pixels long.
+ ld a, e
+ cp 27
+ ld d, 0 ; green
+ jr nc, .gotColor
+ cp 10
+ inc d ; yellow
+ jr nc, .gotColor
+ inc d ; red
+.gotColor
+ ld [hl], d
+ ret
+
+; Copy the current map's sprites' tile patterns to VRAM again after they have
+; been overwritten by other tile patterns.
+ReloadMapSpriteTilePatterns:: ; 3e08 (0:3e08)
+ ld hl, wFontLoaded
+ ld a, [hl]
+ push af
+ res 0, [hl]
+ push hl
+ xor a
+ ld [W_SPRITESETID], a
+ call DisableLCD
+ callba InitMapSprites
+ call EnableLCD
+ pop hl
+ pop af
+ ld [hl], a
+ call LoadPlayerSpriteGraphics
+ call LoadFontTilePatterns
+ jp UpdateSprites
+
+
+GiveItem::
+; Give player quantity c of item b,
+; and copy the item's name to wcf4b.
+; Return carry on success.
+ ld a, b
+ ld [wd11e], a
+ ld [wcf91], a
+ ld a, c
+ ld [wcf96], a
+ ld hl,wNumBagItems
+ call AddItemToInventory
+ ret nc
+ call GetItemName
+ call CopyStringToCF4B
+ scf
+ ret
+
+GivePokemon::
+; Give the player monster b at level c.
+ ld a, b
+ ld [wcf91], a
+ ld a, c
+ ld [W_CURENEMYLVL], a
+ xor a
+ ld [wcc49], a
+ ld b, BANK(_GivePokemon)
+ ld hl, _GivePokemon
+ jp Bankswitch
+
+
+Random::
+; Return a random number in a.
+; For battles, use BattleRandom.
+ push hl
+ push de
+ push bc
+ callba Random_
+ ld a, [hRandomAdd]
+ pop bc
+ pop de
+ pop hl
+ ret
+
+
+INCLUDE "home/predef.asm"
+
+
+Func_3ead:: ; 3ead (0:3ead)
+ ld b, BANK(CinnabarGymQuiz_1eb0a)
+ ld hl, CinnabarGymQuiz_1eb0a
+ jp Bankswitch
+
+CheckForHiddenObjectOrBookshelfOrCardKeyDoor:: ; 3eb5 (0:3eb5)
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, [hJoyHeld]
+ bit 0, a ; A button
+ jr z, .nothingFound
+; A button is pressed
+ ld a, Bank(CheckForHiddenObject)
+ ld [MBC1RomBank], a
+ ld [H_LOADEDROMBANK], a
+ call CheckForHiddenObject
+ ld a, [$ffee]
+ and a
+ jr nz, .hiddenObjectNotFound
+ ld a, [wHiddenObjectFunctionRomBank]
+ ld [MBC1RomBank], a
+ ld [H_LOADEDROMBANK], a
+ ld de, .returnAddress
+ push de
+ jp [hl]
+.returnAddress
+ xor a
+ jr .done
+.hiddenObjectNotFound
+ callba PrintBookshelfText
+ ld a, [$ffdb]
+ and a
+ jr z, .done
+.nothingFound
+ ld a, $ff
+.done
+ ld [$ffeb], a
+ pop af
+ ld [MBC1RomBank], a
+ ld [H_LOADEDROMBANK], a
+ ret
+
+PrintPredefTextID:: ; 3ef5 (0:3ef5)
+ ld [H_DOWNARROWBLINKCNT2], a ; $ff8c
+ ld hl, TextPredefs
+ call SetMapTextPointer
+ ld hl, wcf11
+ set 0, [hl]
+ call DisplayTextID
+
+RestoreMapTextPointer:: ; 3f05 (0:3f05)
+ ld hl, W_MAPTEXTPTR
+ ld a, [$ffec]
+ ld [hli], a
+ ld a, [$ffec + 1]
+ ld [hl], a
+ ret
+
+SetMapTextPointer:: ; 3f0f (0:3f0f)
+ ld a, [W_MAPTEXTPTR]
+ ld [$ffec], a
+ ld a, [W_MAPTEXTPTR + 1]
+ ld [$ffec + 1], a
+ ld a, l
+ ld [W_MAPTEXTPTR], a
+ ld a, h
+ ld [W_MAPTEXTPTR + 1], a
+ ret
+
+TextPredefs::
+ add_tx_pre CardKeySuccessText ; 01
+ add_tx_pre CardKeyFailText ; 02
+ add_tx_pre RedBedroomPC ; 03
+ add_tx_pre RedBedroomSNESText ; 04
+ add_tx_pre PushStartText ; 05
+ add_tx_pre SaveOptionText ; 06
+ add_tx_pre StrengthsAndWeaknessesText ; 07
+ add_tx_pre OakLabEmailText ; 08
+ add_tx_pre AerodactylFossilText ; 09
+ add_tx_pre Route15UpstairsBinocularsText ; 0A
+ add_tx_pre KabutopsFossilText ; 0B
+ add_tx_pre GymStatueText1 ; 0C
+ add_tx_pre GymStatueText2 ; 0D
+ add_tx_pre BookcaseText ; 0E
+ add_tx_pre ViridianCityPokecenterBenchGuyText ; 0F
+ add_tx_pre PewterCityPokecenterBenchGuyText ; 10
+ add_tx_pre CeruleanCityPokecenterBenchGuyText ; 11
+ add_tx_pre LavenderCityPokecenterBenchGuyText ; 12
+ add_tx_pre VermilionCityPokecenterBenchGuyText ; 13
+ add_tx_pre CeladonCityPokecenterBenchGuyText ; 14
+ add_tx_pre CeladonCityHotelText ; 15
+ add_tx_pre FuchsiaCityPokecenterBenchGuyText ; 16
+ add_tx_pre CinnabarIslandPokecenterBenchGuyText ; 17
+ add_tx_pre SaffronCityPokecenterBenchGuyText ; 18
+ add_tx_pre MtMoonPokecenterBenchGuyText ; 19
+ add_tx_pre RockTunnelPokecenterBenchGuyText ; 1A
+ add_tx_pre UnusedBenchGuyText1 ; 1B
+ add_tx_pre UnusedBenchGuyText2 ; 1C
+ add_tx_pre UnusedBenchGuyText3 ; 1D
+ add_tx_pre TerminatorText_62508 ; 1E
+ add_tx_pre PredefText1f ; 1F
+ add_tx_pre ViridianSchoolNotebook ; 20
+ add_tx_pre ViridianSchoolBlackboard ; 21
+ add_tx_pre JustAMomentText ; 22
+ add_tx_pre PredefText23 ; 23
+ add_tx_pre FoundHiddenItemText ; 24
+ add_tx_pre HiddenItemBagFullText ; 25
+ add_tx_pre VermilionGymTrashText ; 26
+ add_tx_pre IndigoPlateauHQText ; 27
+ add_tx_pre GameCornerOutOfOrderText ; 28
+ add_tx_pre GameCornerOutToLunchText ; 29
+ add_tx_pre GameCornerSomeonesKeysText ; 2A
+ add_tx_pre FoundHiddenCoinsText ; 2B
+ add_tx_pre DroppedHiddenCoinsText ; 2C
+ add_tx_pre BillsHouseMonitorText ; 2D
+ add_tx_pre BillsHouseInitiatedText ; 2E
+ add_tx_pre BillsHousePokemonList ; 2F
+ add_tx_pre MagazinesText ; 30
+ add_tx_pre CinnabarGymQuiz ; 31
+ add_tx_pre GameCornerNoCoinsText ; 32
+ add_tx_pre GameCornerCoinCaseText ; 33
+ add_tx_pre LinkCableHelp ; 34
+ add_tx_pre TMNotebook ; 35
+ add_tx_pre FightingDojoText ; 36
+ add_tx_pre FightingDojoText_52a10 ; 37
+ add_tx_pre FightingDojoText_52a1d ; 38
+ add_tx_pre NewBicycleText ; 39
+ add_tx_pre IndigoPlateauStatues ; 3A
+ add_tx_pre VermilionGymTrashSuccesText1 ; 3B
+ add_tx_pre VermilionGymTrashSuccesText2 ; 3C
+ add_tx_pre VermilionGymTrashSuccesText3 ; 3D
+ add_tx_pre VermilionGymTrashFailText ; 3E
+ add_tx_pre TownMapText ; 3F
+ add_tx_pre BookOrSculptureText ; 40
+ add_tx_pre ElevatorText ; 41
+ add_tx_pre PokemonStuffText ; 42
diff --git a/home/audio.asm b/home/audio.asm index 9210924c..e062c8da 100644 --- a/home/audio.asm +++ b/home/audio.asm @@ -1,183 +1,186 @@ -PlayDefaultMusic:: ; 2307 (0:2307) - call WaitForSoundToFinish - xor a - ld c, a - ld d, a - ld [wcfca], a - jr asm_2324 - -Func_2312:: ; 2312 (0:2312) - ld c, $a - ld d, $0 - ld a, [wd72e] - bit 5, a - jr z, asm_2324 - xor a - ld [wcfca], a - ld c, $8 - ld d, c -asm_2324:: ; 2324 (0:2324) - ld a, [wWalkBikeSurfState] - and a - jr z, .asm_2343 - cp $2 - jr z, .asm_2332 - ld a, MUSIC_BIKE_RIDING - jr .asm_2334 -.asm_2332 - ld a, MUSIC_SURFING -.asm_2334 - ld b, a - ld a, d - and a - ld a, BANK(Music_BikeRiding) - jr nz, .asm_233e - ld [wc0ef], a -.asm_233e - ld [wc0f0], a - jr .asm_234c -.asm_2343 - ld a, [wd35b] - ld b, a - call Func_2385 - jr c, .asm_2351 -.asm_234c - ld a, [wcfca] - cp b - ret z -.asm_2351 - ld a, c - ld [wMusicHeaderPointer], a - ld a, b - ld [wcfca], a - ld [wc0ee], a - jp PlaySound - -Func_235f:: ; 235f (0:235f) - ld a, [wc0ef] - ld b, a - cp BANK(Music2_UpdateMusic) - jr nz, .checkForBank08 -.bank02 - ld hl, Music2_UpdateMusic - jr .asm_2378 -.checkForBank08 - cp BANK(Music8_UpdateMusic) - jr nz, .bank1F -.bank08 - ld hl, Music8_UpdateMusic - jr .asm_2378 -.bank1F - ld hl, Music1f_UpdateMusic -.asm_2378 - ld c, $6 -.asm_237a - push bc - push hl - call Bankswitch - pop hl - pop bc - dec c - jr nz, .asm_237a - ret - -Func_2385:: ; 2385 (0:2385) - ld a, [wd35c] - ld e, a - ld a, [wc0ef] - cp e - jr nz, .asm_2394 - ld [wc0f0], a - and a - ret -.asm_2394 - ld a, c - and a - ld a, e - jr nz, .asm_239c - ld [wc0ef], a -.asm_239c - ld [wc0f0], a - scf - ret - -PlayMusic:: ; 23a1 (0:23a1) - ld b, a - ld [wc0ee], a - xor a - ld [wMusicHeaderPointer], a - ld a, c - ld [wc0ef], a - ld [wc0f0], a - ld a, b - -; plays music specified by a. If value is $ff, music is stopped -PlaySound:: ; 23b1 (0:23b1) - push hl - push de - push bc - ld b, a - ld a, [wc0ee] - and a - jr z, .asm_23c8 - xor a - ld [wc02a], a - ld [wc02b], a - ld [wc02c], a - ld [wc02d], a -.asm_23c8 - ld a, [wMusicHeaderPointer] - and a - jr z, .asm_23e3 - ld a, [wc0ee] - and a - jr z, .asm_2425 - xor a - ld [wc0ee], a - ld a, [wcfca] - cp $ff - jr nz, .asm_2414 - xor a - ld [wMusicHeaderPointer], a -.asm_23e3 - xor a - ld [wc0ee], a - ld a, [H_LOADEDROMBANK] - ld [$ffb9], a - ld a, [wc0ef] - ld [H_LOADEDROMBANK], a - ld [$2000], a - cp BANK(Func_9876) - jr nz, .checkForBank08 -.bank02 - ld a, b - call Func_9876 - jr .asm_240b -.checkForBank08 - cp BANK(Func_22035) - jr nz, .bank1F -.bank08 - ld a, b - call Func_22035 - jr .asm_240b -.bank1F - ld a, b - call Func_7d8ea -.asm_240b - ld a, [$ffb9] - ld [H_LOADEDROMBANK], a - ld [$2000], a - jr .asm_2425 -.asm_2414 - ld a, b - ld [wcfca], a - ld a, [wMusicHeaderPointer] - ld [wcfc8], a - ld [wcfc9], a - ld a, b - ld [wMusicHeaderPointer], a -.asm_2425 - pop bc - pop de - pop hl - ret +PlayDefaultMusic:: ; 2307 (0:2307)
+ call WaitForSoundToFinish
+ xor a
+ ld c, a
+ ld d, a
+ ld [wcfca], a
+ jr asm_2324
+
+Func_2312:: ; 2312 (0:2312)
+ ld c, $a
+ ld d, $0
+ ld a, [wd72e]
+ bit 5, a
+ jr z, asm_2324
+ xor a
+ ld [wcfca], a
+ ld c, $8
+ ld d, c
+asm_2324:: ; 2324 (0:2324)
+ ld a, [wWalkBikeSurfState]
+ and a
+ jr z, .asm_2343
+ cp $2
+ jr z, .asm_2332
+ ld a, MUSIC_BIKE_RIDING
+ jr .asm_2334
+.asm_2332
+ ld a, MUSIC_SURFING
+.asm_2334
+ ld b, a
+ ld a, d
+ and a
+ ld a, BANK(Music_BikeRiding)
+ jr nz, .asm_233e
+ ld [wc0ef], a
+.asm_233e
+ ld [wc0f0], a
+ jr .asm_234c
+.asm_2343
+ ld a, [wd35b]
+ ld b, a
+ call Func_2385
+ jr c, .asm_2351
+.asm_234c
+ ld a, [wcfca]
+ cp b
+ ret z
+.asm_2351
+ ld a, c
+ ld [wMusicHeaderPointer], a
+ ld a, b
+ ld [wcfca], a
+ ld [wc0ee], a
+ jp PlaySound
+
+Func_235f:: ; 235f (0:235f)
+ ld a, [wc0ef]
+ ld b, a
+ cp BANK(Music2_UpdateMusic)
+ jr nz, .checkForBank08
+.bank02
+ ld hl, Music2_UpdateMusic
+ jr .asm_2378
+.checkForBank08
+ cp BANK(Music8_UpdateMusic)
+ jr nz, .bank1F
+.bank08
+ ld hl, Music8_UpdateMusic
+ jr .asm_2378
+.bank1F
+ ld hl, Music1f_UpdateMusic
+.asm_2378
+ ld c, $6
+.asm_237a
+ push bc
+ push hl
+ call Bankswitch
+ pop hl
+ pop bc
+ dec c
+ jr nz, .asm_237a
+ ret
+
+Func_2385:: ; 2385 (0:2385)
+ ld a, [wd35c]
+ ld e, a
+ ld a, [wc0ef]
+ cp e
+ jr nz, .asm_2394
+ ld [wc0f0], a
+ and a
+ ret
+.asm_2394
+ ld a, c
+ and a
+ ld a, e
+ jr nz, .asm_239c
+ ld [wc0ef], a
+.asm_239c
+ ld [wc0f0], a
+ scf
+ ret
+
+PlayMusic:: ; 23a1 (0:23a1)
+ ld b, a
+ ld [wc0ee], a
+ xor a
+ ld [wMusicHeaderPointer], a
+ ld a, c
+ ld [wc0ef], a
+ ld [wc0f0], a
+ ld a, b
+
+StopAllMusic:: ; 2233 (0:2233)
+ ld a,$FF
+ ld [wc0ee],a
+; plays music specified by a. If value is $ff, music is stopped
+PlaySound:: ; 23b1 (0:23b1)
+ push hl
+ push de
+ push bc
+ ld b, a
+ ld a, [wc0ee]
+ and a
+ jr z, .asm_23c8
+ xor a
+ ld [wc02a], a
+ ld [wc02b], a
+ ld [wc02c], a
+ ld [wc02d], a
+.asm_23c8
+ ld a, [wMusicHeaderPointer]
+ and a
+ jr z, .asm_23e3
+ ld a, [wc0ee]
+ and a
+ jr z, .asm_2425
+ xor a
+ ld [wc0ee], a
+ ld a, [wcfca]
+ cp $ff
+ jr nz, .asm_2414
+ xor a
+ ld [wMusicHeaderPointer], a
+.asm_23e3
+ xor a
+ ld [wc0ee], a
+ ld a, [H_LOADEDROMBANK]
+ ld [$ffb9], a
+ ld a, [wc0ef]
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ cp BANK(Func_9876)
+ jr nz, .checkForBank08
+.bank02
+ ld a, b
+ call Func_9876
+ jr .asm_240b
+.checkForBank08
+ cp BANK(Func_22035)
+ jr nz, .bank1F
+.bank08
+ ld a, b
+ call Func_22035
+ jr .asm_240b
+.bank1F
+ ld a, b
+ call Func_7d8ea
+.asm_240b
+ ld a, [$ffb9]
+ ld [H_LOADEDROMBANK], a
+ ld [$2000], a
+ jr .asm_2425
+.asm_2414
+ ld a, b
+ ld [wcfca], a
+ ld a, [wMusicHeaderPointer]
+ ld [wcfc8], a
+ ld [wcfc9], a
+ ld a, b
+ ld [wMusicHeaderPointer], a
+.asm_2425
+ pop bc
+ pop de
+ pop hl
+ ret
diff --git a/home/init.asm b/home/init.asm index cc89ad34..701a4bb8 100644 --- a/home/init.asm +++ b/home/init.asm @@ -1,137 +1,136 @@ -SoftReset:: - call StopAllSounds - call GBPalWhiteOut - ld c, $20 - call DelayFrames - ; fallthrough - -Init:: -; Program init. - -rLCDC_DEFAULT EQU %11100011 -; * LCD enabled -; * Window tile map at $9C00 -; * Window display enabled -; * BG and window tile data at $8800 -; * BG tile map at $9800 -; * 8x8 OBJ size -; * OBJ display enabled -; * BG display enabled - - di - - xor a - ld [rIF], a - ld [rIE], a - ld [$ff43], a - ld [$ff42], a - ld [rSB], a - ld [rSC], a - ld [$ff4b], a - ld [$ff4a], a - ld [$ff06], a - ld [$ff07], a - ld [$ff47], a - ld [$ff48], a - ld [$ff49], a - - ld a, rLCDC_ENABLE_MASK - ld [rLCDC], a - call DisableLCD - - ld sp, wStack - - ld hl, $c000 ; start of WRAM - ld bc, $2000 ; size of WRAM -.loop - ld [hl], 0 - inc hl - dec bc - ld a, b - or c - jr nz, .loop - - call ClearVram - - ld hl, $ff80 - ld bc, $ffff - $ff80 - call FillMemory - - call ClearSprites - - ld a, Bank(WriteDMACodeToHRAM) - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a - call WriteDMACodeToHRAM - - xor a - ld [hTilesetType], a - ld [$ff41], a - ld [hSCX], a - ld [hSCY], a - ld [$ff0f], a - ld a, 1 << VBLANK + 1 << TIMER + 1 << SERIAL - ld [rIE], a - - ld a, 144 ; move the window off-screen - ld [hWY], a - ld [rWY], a - ld a, 7 - ld [rWX], a - - ld a, CONNECTION_NOT_ESTABLISHED - ld [hSerialConnectionStatus], a - - ld h, vBGMap0 / $100 - call ClearBgMap - ld h, vBGMap1 / $100 - call ClearBgMap - - ld a, rLCDC_DEFAULT - ld [rLCDC], a - ld a, 16 - ld [hSoftReset], a - call StopAllSounds - - ei - - predef LoadSGB - - ld a, BANK(SFX_1f_67) - ld [wc0ef], a - ld [wc0f0], a - ld a, $9c - ld [$ffbd], a - xor a - ld [$ffbc], a - dec a - ld [wUpdateSpritesEnabled], a - - predef PlayIntro - - call DisableLCD - call ClearVram - call GBPalNormal - call ClearSprites - ld a, rLCDC_DEFAULT - ld [rLCDC], a - - jp SetDefaultNamesBeforeTitlescreen - -ClearVram: - ld hl, $8000 - ld bc, $2000 - xor a - jp FillMemory - - -StopAllSounds:: - ld a, BANK(Music2_UpdateMusic) - ld [wc0ef], a - ld [wc0f0], a - xor a - ld [wMusicHeaderPointer], a - ld [wc0ee], a - ld [wcfca], a - dec a - jp PlaySound +SoftReset::
+ call StopAllSounds
+ call GBPalWhiteOut
+ ld c, $20
+ call DelayFrames
+ ; fallthrough
+
+Init::
+; Program init.
+
+rLCDC_DEFAULT EQU %11100011
+; * LCD enabled
+; * Window tile map at $9C00
+; * Window display enabled
+; * BG and window tile data at $8800
+; * BG tile map at $9800
+; * 8x8 OBJ size
+; * OBJ display enabled
+; * BG display enabled
+
+ di
+
+ xor a
+ ld [rIF], a
+ ld [rIE], a
+ ld [$ff43], a
+ ld [$ff42], a
+ ld [rSB], a
+ ld [rSC], a
+ ld [$ff4b], a
+ ld [$ff4a], a
+ ld [$ff06], a
+ ld [$ff07], a
+ ld [$ff47], a
+ ld [$ff48], a
+ ld [$ff49], a
+
+ ld a, rLCDC_ENABLE_MASK
+ ld [rLCDC], a
+ call DisableLCD
+
+ ld sp, wStack
+
+ ld hl, $c000 ; start of WRAM
+ ld bc, $2000 ; size of WRAM
+.loop
+ ld [hl], 0
+ inc hl
+ dec bc
+ ld a, b
+ or c
+ jr nz, .loop
+
+ call ClearVram
+
+ ld hl, $ff80
+ ld bc, $ffff - $ff80
+ call FillMemory
+
+ call ClearSprites
+
+ ld a, Bank(WriteDMACodeToHRAM)
+ ld [H_LOADEDROMBANK], a
+ ld [MBC1RomBank], a
+ call WriteDMACodeToHRAM
+
+ xor a
+ ld [hTilesetType], a
+ ld [$ff41], a
+ ld [hSCX], a
+ ld [hSCY], a
+ ld [$ff0f], a
+ ld a, 1 << VBLANK + 1 << TIMER + 1 << SERIAL
+ ld [rIE], a
+
+ ld a, 144 ; move the window off-screen
+ ld [hWY], a
+ ld [rWY], a
+ ld a, 7
+ ld [rWX], a
+
+ ld a, CONNECTION_NOT_ESTABLISHED
+ ld [hSerialConnectionStatus], a
+
+ ld h, vBGMap0 / $100
+ call ClearBgMap
+ ld h, vBGMap1 / $100
+ call ClearBgMap
+
+ ld a, rLCDC_DEFAULT
+ ld [rLCDC], a
+ ld a, 16
+ ld [hSoftReset], a
+ call StopAllSounds
+
+ ei
+
+ predef LoadSGB
+
+ ld a, BANK(SFX_1f_67)
+ ld [wc0ef], a
+ ld [wc0f0], a
+ ld a, $9c
+ ld [$ffbd], a
+ xor a
+ ld [$ffbc], a
+ dec a
+ ld [wUpdateSpritesEnabled], a
+
+ predef PlayIntro
+
+ call DisableLCD
+ call ClearVram
+ call GBPalNormal
+ call ClearSprites
+ ld a, rLCDC_DEFAULT
+ ld [rLCDC], a
+
+ jp SetDefaultNamesBeforeTitlescreen
+
+ClearVram:
+ ld hl, $8000
+ ld bc, $2000
+ xor a
+ jp FillMemory
+
+
+StopAllSounds::
+ ld a, BANK(Music2_UpdateMusic)
+ ld [wc0ef], a
+ ld [wc0f0], a
+ xor a
+ ld [wMusicHeaderPointer], a
+ ld [wc0ee], a
+ ld [wcfca], a
+ jp StopAllMusic
diff --git a/home/overworld.asm b/home/overworld.asm index 0a92355c..3309f1cc 100644 --- a/home/overworld.asm +++ b/home/overworld.asm @@ -1,2225 +1,2293 @@ -EnterMap:: ; 01d7 (0:01d7) -; Load a new map. - ld a, $ff - ld [wJoyIgnore], a - call LoadMapData - callba ClearVariablesAfterLoadingMapData - ld hl, wd72c - bit 0, [hl] ; has the player already made 3 steps since the last battle? - jr z, .skipGivingThreeStepsOfNoRandomBattles - ld a, 3 ; minimum number of steps between battles - ld [wNumberOfNoRandomBattleStepsLeft], a -.skipGivingThreeStepsOfNoRandomBattles - ld hl, wd72e - bit 5, [hl] ; did a battle happen immediately before this? - res 5, [hl] ; unset the "battle just happened" flag - call z, ResetUsingStrengthOutOfBattleBit - call nz, MapEntryAfterBattle - ld hl, wd732 - ld a, [hl] - and 1 << 4 | 1 << 3 ; fly warp or dungeon warp - jr z, .didNotEnterUsingFlyWarpOrDungeonWarp - callba EnterMapAnim - call UpdateSprites - ld hl, wd732 - res 3, [hl] - ld hl, wd72e - res 4, [hl] - call Func_342a -.didNotEnterUsingFlyWarpOrDungeonWarp - callba CheckForceBikeOrSurf ; handle currents in SF islands and forced bike riding in cycling road - ld hl, wd732 - bit 4, [hl] - res 4, [hl] - ld hl, wd72d - res 5, [hl] - call UpdateSprites - ld hl, wd126 - set 5, [hl] - set 6, [hl] - xor a - ld [wJoyIgnore], a - -OverworldLoop:: ; 0242 (0:0242) - call DelayFrame -OverworldLoopLessDelay:: ; 0245 (0:0245) - call DelayFrame - call Func_342a - call LoadGBPal - ld a,[wWalkCounter] - and a - jp nz,.moveAhead ; if the player sprite has not yet completed the walking animation - call JoypadOverworld ; get joypad state (which is possibly simulated) - callba SafariZoneCheck - ld a,[wSafariZoneGameOver] - and a - jp nz,WarpFound2 - ld hl,wd72d - bit 3,[hl] - res 3,[hl] - jp nz,WarpFound2 - ld a,[wd732] - and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp - jp nz,HandleFlyWarpOrDungeonWarp - ld a,[W_CUROPPONENT] - and a - jp nz,.newBattle - ld a,[wd730] - bit 7,a ; are we simulating button presses? - jr z,.notSimulating - ld a,[hJoyHeld] - jr .checkIfStartIsPressed -.notSimulating - ld a,[hJoyPressed] -.checkIfStartIsPressed - bit 3,a ; start button - jr z,.startButtonNotPressed -; if START is pressed - xor a - ld [hSpriteIndexOrTextID],a ; start menu text ID - jp .displayDialogue -.startButtonNotPressed - bit 0,a ; A button - jp z,.checkIfDownButtonIsPressed -; if A is pressed - ld a,[wd730] - bit 2,a - jp nz,.noDirectionButtonsPressed - call IsPlayerCharacterBeingControlledByGame - jr nz,.checkForOpponent - call CheckForHiddenObjectOrBookshelfOrCardKeyDoor - ld a,[$ffeb] - and a - jp z,OverworldLoop ; jump if a hidden object or bookshelf was found, but not if a card key door was found - xor a - ld [wd436],a ; new yellow address - call IsSpriteOrSignInFrontOfPlayer - call Func_0ffe - ld a,[hSpriteIndexOrTextID] - and a - jp z,OverworldLoop -.displayDialogue - predef GetTileAndCoordsInFrontOfPlayer - call UpdateSprites - ld a,[wFlags_0xcd60] - bit 2,a - jr nz,.checkForOpponent - bit 0,a - jr nz,.checkForOpponent - aCoord 8, 9 - ld [wcf0e],a - call DisplayTextID ; display either the start menu or the NPC/sign text - ld a,[wcc47] - and a - jr z,.checkForOpponent - xor a - ld [wcc47],a - jp EnterMap -; predef LoadSAV -; ld a,[W_CURMAP] -; ld [wDestinationMap],a -; call SpecialWarpIn -; ld a,[W_CURMAP] -; call SwitchToMapRomBank ; switch to the ROM bank of the current map -; ld hl,W_CURMAPTILESET -; set 7,[hl] -.checkForOpponent - ld a,[W_CUROPPONENT] - and a - jp nz,.newBattle - jp OverworldLoop -.noDirectionButtonsPressed - call UpdateSprites ; 231c - ld hl,wFlags_0xcd60 - res 2,[hl] - xor a - ld [wd435], a - ld a, $1 - ld a,$01 - ld [wcc4b],a - ld a,[wd528] ; the direction that was pressed last time - and a - jr z, .overworldloop -; if a direction was pressed last time - ld [wd529],a ; save the last direction - xor a - ld [wd528],a ; zero the direction -.overworldloop - jp OverworldLoop -.checkIfDownButtonIsPressed - ld a,[hJoyHeld] ; current joypad state - bit 7,a ; down button - jr z,.checkIfUpButtonIsPressed - ld a,$01 - ld [wSpriteStateData1 + 3],a - ld a,$04 - jr .handleDirectionButtonPress -.checkIfUpButtonIsPressed - bit 6,a ; up button - jr z,.checkIfLeftButtonIsPressed - ld a,$ff - ld [wSpriteStateData1 + 3],a - ld a,$08 - jr .handleDirectionButtonPress -.checkIfLeftButtonIsPressed - bit 5,a ; left button - jr z,.checkIfRightButtonIsPressed - ld a,$ff - ld [wSpriteStateData1 + 5],a - ld a,$02 - jr .handleDirectionButtonPress -.checkIfRightButtonIsPressed - bit 4,a ; right button - jr z,.noDirectionButtonsPressed - ld a,$01 - ld [wSpriteStateData1 + 5],a -.handleDirectionButtonPress - ld [wd52a],a ; new direction - ld a,[wd730] - bit 7,a ; are we simulating button presses? - jr nz,.noDirectionChange ; ignore direction changes if we are - ld a,[wcc4b] - and a - jr z,.noDirectionChange - ld a,[wd52a] ; new direction - ld b,a - ld a,[wd529] ; old direction - cp b - jr z,.noDirectionChange - ld a,$8 - ld [wd434],a -; unlike in red/blue, yellow does not have the 180 degrees odd code - ld hl,wFlags_0xcd60 - set 2,[hl] - xor a - ld [wcc4b],a - ld a,[wd52a] - ld [wd528],a - call NewBattle - jp c,.battleOccurred - jp OverworldLoop -.noDirectionChange - ld a,[wd52a] ; current direction - ld [wd528],a ; save direction - call UpdateSprites - ld a,[wWalkBikeSurfState] - cp a,$02 ; surfing - jr z,.surfing -; not surfing - call CollisionCheckOnLand - jr nc,.noCollision -; collision occurred - push hl - ld hl,wd736 - bit 2,[hl] ; standing on warp flag - pop hl - jp z,OverworldLoop -; collision occurred while standing on a warp - push hl - call ExtraWarpCheck ; sets carry if there is a potential to warp - pop hl - jp c,CheckWarpsCollision - jp OverworldLoop -.surfing - call CollisionCheckOnWater - jp c,OverworldLoop -.noCollision - ld a,$08 - ld [wWalkCounter],a - callab Func_fcc08 - jr .moveAhead2 -.moveAhead - call IsSpinning - call UpdateSprites ; move sprites -.moveAhead2 - ld hl,wFlags_0xcd60 - res 2,[hl] - xor a - ld [wd435],a - call DoBikeSpeedup - call AdvancePlayerSprite - ld a,[wWalkCounter] - and a - jp nz,CheckMapConnections ; it seems like this check will never succeed (the other place where CheckMapConnections is run works) -; walking animation finished - call StepCountCheck - ld a,[wd790] - bit 7,a ; in the safari zone? - jr z,.notSafariZone - callba SafariZoneCheckSteps - ld a,[wSafariZoneGameOver] - and a - jp nz,WarpFound2 -.notSafariZone - ld a,[W_ISINBATTLE] - and a - jp nz,CheckWarpsNoCollision - predef ApplyOutOfBattlePoisonDamage ; also increment daycare mon exp - ld a,[wd12d] - and a - jp nz,HandleBlackOut ; if all pokemon fainted -.newBattle - call NewBattle - ld hl,wd736 - res 2,[hl] ; standing on warp flag - jp nc,CheckWarpsNoCollision ; check for warps if there was no battle -.battleOccurred - ld hl,wd72d - res 6,[hl] - ld hl,W_FLAGS_D733 - res 3,[hl] - ld hl,wd126 - set 5,[hl] - set 6,[hl] - xor a - ld [hJoyHeld],a - ld a,[W_CURMAP] - cp a,CINNABAR_GYM - jr nz,.notCinnabarGym - ld hl,wd79b - set 7,[hl] -.notCinnabarGym - ld hl,wd72e - set 5,[hl] - ld a,[W_CURMAP] - cp a,OAKS_LAB - jp z,.noFaintCheck ; no blacking out if the player lost to the rival in Oak's lab - callab AnyPartyAlive - ld a,d - and a - jr z,.allPokemonFainted -.noFaintCheck - ld c,$0a - call DelayFrames - jp EnterMap -;.allPokemonFainted -; ld a,$ff -; ld [W_ISINBATTLE],a -; call RunMapScript -; jp HandleBlackOut - -StepCountCheck:: ; 0457 (0:0457) - ld a,[wd730] - bit 7,a - jr nz,.doneStepCounting ; if button presses are being simulated, don't count steps -; step counting - ld hl,wStepCounter - dec [hl] - ld a,[wd72c] - bit 0,a - jr z,.doneStepCounting - ld hl,wNumberOfNoRandomBattleStepsLeft - dec [hl] - jr nz,.doneStepCounting - ld hl,wd72c - res 0,[hl] ; indicate that the player has stepped thrice since the last battle -.doneStepCounting - ret - -; function to determine if there will be a battle and execute it (either a trainer battle or wild battle) -; sets carry if a battle occurred and unsets carry if not -NewBattle:: ; 0480 (0:0480) - ld a,[wd72d] - bit 4,a - jr nz,.noBattle - call IsPlayerCharacterBeingControlledByGame - jr nz,.noBattle ; no battle if the player character is under the game's control - ld a,[wd72e] - bit 4,a - jr nz,.noBattle - ld b, BANK(InitBattle) - ld hl, InitBattle ; 3d:5ff2 - jp Bankswitch -.noBattle - and a - ret - -DoBikeSpeedup:: ; 049d (0:049d) - ld a,[wWalkBikeSurfState] - dec a ; riding a bike? - ret nz - ld a,[wd736] - bit 6,a - ret nz - ld a,[wNPCMovementScriptPointerTableNum] - and a - ret nz - ld a,[W_CURMAP] - cp ROUTE_17 ; cycling road - jr nz,.goFaster - ld a,[hJoyHeld] - and a,D_UP | D_LEFT | D_RIGHT - ret nz -.goFaster - call AdvancePlayerSprite - ret - -; check if the player has stepped onto a warp after having not collided -CheckWarpsNoCollision:: ; 04bd (0:04bd) - ld a,[wNumberOfWarps] - and a - jp z,CheckMapConnections - ld b,0 - ld a,[wNumberOfWarps] - ld c,a - ld a,[W_YCOORD] - ld d,a - ld a,[W_XCOORD] - ld e,a - ld hl,wWarpEntries -CheckWarpsNoCollisionLoop:: ; 04d5 (0:04d5) - ld a,[hli] ; check if the warp's Y position matches - cp d - jr nz,CheckWarpsNoCollisionRetry1 - ld a,[hli] ; check if the warp's X position matches - cp e - jr nz,CheckWarpsNoCollisionRetry2 -; if a match was found - push hl - push bc - ld hl,wd736 - set 2,[hl] ; standing on warp flag - callba IsPlayerStandingOnDoorTileOrWarpTile - pop bc - pop hl - jr c,WarpFound1 ; jump if standing on door or warp - push hl - push bc - call ExtraWarpCheck - pop bc - pop hl - jr nc,CheckWarpsNoCollisionRetry2 -; if the extra check passed - ld a,[W_FLAGS_D733] - bit 2,a - jr nz,WarpFound1 - push de - push bc - call Joypad - pop bc - pop de - ld a,[hJoyHeld] - and a,D_DOWN | D_UP | D_LEFT | D_RIGHT - jr z,CheckWarpsNoCollisionRetry2 ; if directional buttons aren't being pressed, do not pass through the warp - jr WarpFound1 - -CheckWarpsNoCollisionRetry1:: ; 050f (0:050f) - inc hl -CheckWarpsNoCollisionRetry2:: ; 0510 (0:0510) - inc hl - inc hl -ContinueCheckWarpsNoCollisionLoop:: ; 0512 (0:0512) - inc b ; increment warp number - dec c ; decrement number of warps - jp nz,CheckWarpsNoCollisionLoop - jp CheckMapConnections - -; check if the player has stepped onto a warp after having collided -CheckWarpsCollision:: ; 0706 (0:0706) - ld a,[wNumberOfWarps] - ld c,a - ld hl,wWarpEntries -.loop - ld a,[hli] ; Y coordinate of warp - ld b,a - ld a,[W_YCOORD] - cp b - jr nz,.retry1 - ld a,[hli] ; X coordinate of warp - ld b,a - ld a,[W_XCOORD] - cp b - jr nz,.retry2 - ld a,[hli] - ld [wDestinationWarpID],a - ld a,[hl] - ld [$ff8b],a ; save target map - jr WarpFound2 -.retry1 - inc hl -.retry2 - inc hl - inc hl - dec c - jr nz,.loop - jp OverworldLoop - -WarpFound1:: ; 0735 (0:0735) - ld a,[hli] - ld [wDestinationWarpID],a - ld a,[hli] - ld [$ff8b],a ; save target map - -WarpFound2:: ; 073c (0:073c) - ld a,[wNumberOfWarps] - sub c - ld [wd73b],a ; save ID of used warp - ld a,[W_CURMAP] - ld [wd73c],a - call CheckIfInOutsideMap - jr nz,.indoorMaps -; this is for handling "outside" maps that can't have the 0xFF destination map - ld a,[W_CURMAP] - ld [wLastMap],a - ld a,[W_CURMAPWIDTH] - ld [wd366],a - ld a,[$ff8b] ; destination map number - ld [W_CURMAP],a ; change current map to destination map - cp a,ROCK_TUNNEL_1 - jr nz,.notRockTunnel - ld a,$06 - ld [wMapPalOffset],a - call GBFadeOutToBlack -.notRockTunnel - callab Func_fc5fa ; 3f:45fa - call PlayMapChangeSound - jr .done -; for maps that can have the 0xFF destination map, which means to return to the outside map; not all these maps are necessarily indoors, though -.indoorMaps - ld a,[$ff8b] ; destination map - cp a,$ff - jr z,.goBackOutside -; if not going back to the previous map - ld [W_CURMAP],a ; current map number - callba IsPlayerStandingOnWarpPadOrHole - ld a,[wcd5b] - dec a ; is the player on a warp pad? - jr nz,.notWarpPad -; if the player is on a warp pad - call LeaveMapAnim - ld hl,wd732 - set 3,[hl] - jr .skipMapChangeSound -.notWarpPad - call PlayMapChangeSound -.skipMapChangeSound - ld hl,wd736 - res 0,[hl] - res 1,[hl] - callab Func_fc65b ; 3f:465b - jr .done -.goBackOutside - callab Func_fc69a ; 3f:469a - ; continue from here - ld a,[wLastMap] - ld [W_CURMAP],a - call PlayMapChangeSound - xor a - ld [wMapPalOffset],a -.done - ld hl,wd736 - set 0,[hl] ; have the player's sprite step out from the door (if there is one) - call IgnoreInputForHalfSecond - jp EnterMap - -; if no matching warp was found -CheckMapConnections:: ; 05db (0:05db) -.checkWestMap - ld a,[W_XCOORD] - cp a,$ff - jr nz,.checkEastMap - ld a,[W_MAPCONN3PTR] - ld [W_CURMAP],a - ld a,[wd38f] ; new X coordinate upon entering west map - ld [W_XCOORD],a - ld a,[W_YCOORD] - ld c,a - ld a,[wd38e] ; Y adjustment upon entering west map - add c - ld c,a - ld [W_YCOORD],a - ld a,[wd390] ; pointer to upper left corner of map without adjustment for Y position - ld l,a - ld a,[wd391] - ld h,a - srl c - jr z,.savePointer1 -.pointerAdjustmentLoop1 - ld a,[wd38d] ; width of connected map - add a,$06 - ld e,a - ld d,$00 - ld b,$00 - add hl,de - dec c - jr nz,.pointerAdjustmentLoop1 -.savePointer1 - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a - jp .loadNewMap -.checkEastMap - ld b,a - ld a,[wd525] ; map width - cp b - jr nz,.checkNorthMap - ld a,[W_MAPCONN4PTR] - ld [W_CURMAP],a - ld a,[wd39a] ; new X coordinate upon entering east map - ld [W_XCOORD],a - ld a,[W_YCOORD] - ld c,a - ld a,[wd399] ; Y adjustment upon entering east map - add c - ld c,a - ld [W_YCOORD],a - ld a,[wd39b] ; pointer to upper left corner of map without adjustment for Y position - ld l,a - ld a,[wd39c] - ld h,a - srl c - jr z,.savePointer2 -.pointerAdjustmentLoop2 - ld a,[wd398] - add a,$06 - ld e,a - ld d,$00 - ld b,$00 - add hl,de - dec c - jr nz,.pointerAdjustmentLoop2 -.savePointer2 - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a - jp .loadNewMap -.checkNorthMap - ld a,[W_YCOORD] - cp a,$ff - jr nz,.checkSouthMap - ld a,[W_MAPCONN1PTR] - ld [W_CURMAP],a - ld a,[wd378] ; new Y coordinate upon entering north map - ld [W_YCOORD],a - ld a,[W_XCOORD] - ld c,a - ld a,[wd379] ; X adjustment upon entering north map - add c - ld c,a - ld [W_XCOORD],a - ld a,[wd37a] ; pointer to upper left corner of map without adjustment for X position - ld l,a - ld a,[wd37b] - ld h,a - ld b,$00 - srl c - add hl,bc - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a - jp .loadNewMap -.checkSouthMap - ld b,a - ld a,[wd524] - cp b - jr nz,.didNotEnterConnectedMap - ld a,[W_MAPCONN2PTR] - ld [W_CURMAP],a - ld a,[wd383] ; new Y coordinate upon entering south map - ld [W_YCOORD],a - ld a,[W_XCOORD] - ld c,a - ld a,[wd384] ; X adjustment upon entering south map - add c - ld c,a - ld [W_XCOORD],a - ld a,[wd385] ; pointer to upper left corner of map without adjustment for X position - ld l,a - ld a,[wd386] - ld h,a - ld b,$00 - srl c - add hl,bc - ld a,l - ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section - ld a,h - ld [wCurrentTileBlockMapViewPointer + 1],a -.loadNewMap ; load the connected map that was entered - call LoadMapHeader - call Func_2312 ; music - ld b,$09 - call GoPAL_SET -; Since the sprite set shouldn't change, this will just update VRAM slots at -; $C2XE without loading any tile patterns. - callba InitMapSprites - call LoadTileBlockMap - jp OverworldLoopLessDelay -.didNotEnterConnectedMap - jp OverworldLoop - -; function to play a sound when changing maps -PlayMapChangeSound:: ; 08c9 (0:08c9) - aCoord 8, 8 ; upper left tile of the 4x4 square the player's sprite is standing on - cp a,$0b ; door tile in tileset 0 - jr nz,.didNotGoThroughDoor - ld a,(SFX_02_57 - SFX_Headers_02) / 3 - jr .playSound -.didNotGoThroughDoor - ld a,(SFX_02_5c - SFX_Headers_02) / 3 -.playSound - call PlaySound - ld a,[wMapPalOffset] - and a - ret nz - jp GBFadeOutToBlack - -CheckIfInOutsideMap:: ; 08e1 (0:08e1) -; If the player is in an outside map (a town or route), set the z flag - ld a, [W_CURMAPTILESET] - and a ; most towns/routes have tileset 0 (OVERWORLD) - ret z - cp PLATEAU ; Route 23 / Indigo Plateau - ret - -; this function is an extra check that sometimes has to pass in order to warp, beyond just standing on a warp -; the "sometimes" qualification is necessary because of CheckWarpsNoCollision's behavior -; depending on the map, either "function 1" or "function 2" is used for the check -; "function 1" passes when the player is at the edge of the map and is facing towards the outside of the map -; "function 2" passes when the the tile in front of the player is among a certain set -; sets carry if the check passes, otherwise clears carry -ExtraWarpCheck:: ; 08e9 (0:08e9) - ld a, [W_CURMAP] - cp SS_ANNE_3 - jr z, .useFunction1 - cp ROCKET_HIDEOUT_1 - jr z, .useFunction2 - cp ROCKET_HIDEOUT_2 - jr z, .useFunction2 - cp ROCKET_HIDEOUT_4 - jr z, .useFunction2 - cp ROCK_TUNNEL_1 - jr z, .useFunction2 - ld a, [W_CURMAPTILESET] - and a ; outside tileset (OVERWORLD) - jr z, .useFunction2 - cp SHIP ; S.S. Anne tileset - jr z, .useFunction2 - cp SHIP_PORT ; Vermilion Port tileset - jr z, .useFunction2 - cp PLATEAU ; Indigo Plateau tileset - jr z, .useFunction2 -.useFunction1 - ld hl, IsPlayerFacingEdgeOfMap - jr .doBankswitch -.useFunction2 - ld hl, IsWarpTileInFrontOfPlayer -.doBankswitch - ld b, BANK(IsWarpTileInFrontOfPlayer) - jp Bankswitch - -MapEntryAfterBattle:: ; 091f (0:091f) - callba IsPlayerStandingOnWarp ; for enabling warp testing after collisions - ld a,[wMapPalOffset] - and a - jp z,GBFadeInFromWhite - jp LoadGBPal - -HandleBlackOut:: -; For when all the player's pokemon faint. -; Does not print the "blacked out" message. - - call GBFadeOutToBlack - ld a, $08 - call StopMusic - ld hl, wd72e - res 5, [hl] - ld a, Bank(ResetStatusAndHalveMoneyOnBlackout) ; also Bank(SpecialWarpIn) and Bank(SpecialEnterMap) - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a - call ResetStatusAndHalveMoneyOnBlackout - call SpecialWarpIn - call Func_2312 - jp SpecialEnterMap - -StopMusic:: - ld [wMusicHeaderPointer], a - ld a, $ff - ld [wc0ee], a - call PlaySound -.wait - ld a, [wMusicHeaderPointer] - and a - jr nz, .wait - jp StopAllSounds - -HandleFlyWarpOrDungeonWarp:: ; 0794 (0:0794) - call UpdateSprites - call Delay3 - xor a - ld [wBattleResult], a - ld [wWalkBikeSurfState], a - ld [W_ISINBATTLE], a - ld [wMapPalOffset], a - ld hl, wd732 - set 2, [hl] ; fly warp or dungeon warp - res 5, [hl] ; forced to ride bike - call LeaveMapAnim - ld a, Bank(SpecialWarpIn) - ld [H_LOADEDROMBANK], a - ld [$2000], a - call SpecialWarpIn - jp SpecialEnterMap - -LeaveMapAnim:: ; 07bc (0:07bc) - ld b, BANK(_LeaveMapAnim) - ld hl, _LeaveMapAnim - jp Bankswitch - -LoadPlayerSpriteGraphics:: -; Load sprite graphics based on whether the player is standing, biking, or surfing. - - ; 0: standing - ; 1: biking - ; 2: surfing - - ld a, [wWalkBikeSurfState] - dec a - jr z, .ridingBike - - ld a, [hTilesetType] - and a - jr nz, .determineGraphics - jr .startWalking - -.ridingBike - ; If the bike can't be used, - ; start walking instead. - call IsBikeRidingAllowed - jr c, .determineGraphics - -.startWalking - xor a - ld [wWalkBikeSurfState], a - ld [wWalkBikeSurfStateCopy], a - jp LoadWalkingPlayerSpriteGraphics - -.determineGraphics - ld a, [wWalkBikeSurfState] - and a - jp z, LoadWalkingPlayerSpriteGraphics - dec a - jp z, LoadBikePlayerSpriteGraphics - dec a - jp z, LoadSurfingPlayerSpriteGraphics - jp LoadWalkingPlayerSpriteGraphics - -IsBikeRidingAllowed:: -; The bike can be used on Route 23 and Indigo Plateau, -; or maps with tilesets in BikeRidingTilesets. -; Return carry if biking is allowed. - - ld a, [W_CURMAP] - cp ROUTE_23 - jr z, .allowed - cp INDIGO_PLATEAU - jr z, .allowed - - ld a, [W_CURMAPTILESET] - ld b, a - ld hl, BikeRidingTilesets -.loop - ld a, [hli] - cp b - jr z, .allowed - inc a - jr nz, .loop - and a - ret - -.allowed - scf - ret - -INCLUDE "data/bike_riding_tilesets.asm" - -; load the tile pattern data of the current tileset into VRAM -LoadTilesetTilePatternData:: ; 09e8 (0:09e8) - ld a,[W_TILESETGFXPTR] - ld l,a - ld a,[W_TILESETGFXPTR + 1] - ld h,a - ld de,vTileset - ld bc,$600 - ld a,[W_TILESETBANK] - jp FarCopyData2 - -; this loads the current maps complete tile map (which references blocks, not individual tiles) to C6E8 -; it can also load partial tile maps of connected maps into a border of length 3 around the current map -LoadTileBlockMap:: ; 09fc (0:09fc) -; fill C6E8-CBFB with the background tile - ld hl,wOverworldMap - ld a,[wd3ad] ; background tile number - ld d,a - ld bc,$0514 -.backgroundTileLoop - ld a,d - ld [hli],a - dec bc - ld a,c - or b - jr nz,.backgroundTileLoop -; load tile map of current map (made of tile block IDs) -; a 3-byte border at the edges of the map is kept so that there is space for map connections - ld hl,wOverworldMap - ld a,[W_CURMAPWIDTH] - ld [$ff8c],a - add a,$06 ; border (east and west) - ld [$ff8b],a ; map width + border - ld b,$00 - ld c,a -; make space for north border (next 3 lines) - add hl,bc - add hl,bc - add hl,bc - ld c,$03 - add hl,bc ; this puts us past the (west) border - ld a,[W_MAPDATAPTR] ; tile map pointer - ld e,a - ld a,[W_MAPDATAPTR + 1] - ld d,a ; de = tile map pointer - ld a,[W_CURMAPHEIGHT] - ld b,a -.rowLoop ; copy one row each iteration - push hl - ld a,[$ff8c] ; map width (without border) - ld c,a -.rowInnerLoop - ld a,[de] - inc de - ld [hli],a - dec c - jr nz,.rowInnerLoop -; add the map width plus the border to the base address of the current row to get the next row's address - pop hl - ld a,[$ff8b] ; map width + border - add l - ld l,a - jr nc,.noCarry - inc h -.noCarry - dec b - jr nz,.rowLoop -.northConnection - ld a,[W_MAPCONN1PTR] - cp a,$ff - jr z,.southConnection - call SwitchToMapRomBank - ld a,[wd372] - ld l,a - ld a,[wd373] - ld h,a - ld a,[wd374] - ld e,a - ld a,[wd375] - ld d,a - ld a,[wd376] - ld [$ff8b],a - ld a,[wd377] - ld [$ff8c],a - call LoadNorthSouthConnectionsTileMap -.southConnection - ld a,[W_MAPCONN2PTR] - cp a,$ff - jr z,.westConnection - call SwitchToMapRomBank - ld a,[wd37d] - ld l,a - ld a,[wd37e] - ld h,a - ld a,[wd37f] - ld e,a - ld a,[wd380] - ld d,a - ld a,[wd381] - ld [$ff8b],a - ld a,[wd382] - ld [$ff8c],a - call LoadNorthSouthConnectionsTileMap -.westConnection - ld a,[W_MAPCONN3PTR] - cp a,$ff - jr z,.eastConnection - call SwitchToMapRomBank - ld a,[wd388] - ld l,a - ld a,[wd389] - ld h,a - ld a,[wd38a] - ld e,a - ld a,[wd38b] - ld d,a - ld a,[wd38c] - ld b,a - ld a,[wd38d] - ld [$ff8b],a - call LoadEastWestConnectionsTileMap -.eastConnection - ld a,[W_MAPCONN4PTR] - cp a,$ff - jr z,.done - call SwitchToMapRomBank - ld a,[wd393] - ld l,a - ld a,[wd394] - ld h,a - ld a,[wd395] - ld e,a - ld a,[wd396] - ld d,a - ld a,[wd397] - ld b,a - ld a,[wd398] - ld [$ff8b],a - call LoadEastWestConnectionsTileMap -.done - ret - -LoadNorthSouthConnectionsTileMap:: ; 0ade (0:0ade) - ld c,$03 -.loop - push de - push hl - ld a,[$ff8b] ; width of connection - ld b,a -.innerLoop - ld a,[hli] - ld [de],a - inc de - dec b - jr nz,.innerLoop - pop hl - pop de - ld a,[$ff8c] ; width of connected map - add l - ld l,a - jr nc,.noCarry1 - inc h -.noCarry1 - ld a,[W_CURMAPWIDTH] - add a,$06 - add e - ld e,a - jr nc,.noCarry2 - inc d -.noCarry2 - dec c - jr nz,.loop - ret - -LoadEastWestConnectionsTileMap:: ; 0b02 (0:0b02) - push hl - push de - ld c,$03 -.innerLoop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.innerLoop - pop de - pop hl - ld a,[$ff8b] ; width of connected map - add l - ld l,a - jr nc,.noCarry1 - inc h -.noCarry1 - ld a,[W_CURMAPWIDTH] - add a,$06 - add e - ld e,a - jr nc,.noCarry2 - inc d -.noCarry2 - dec b - jr nz,LoadEastWestConnectionsTileMap - ret - -; function to check if there is a sign or sprite in front of the player -; if so, it is stored in [hSpriteIndexOrTextID] -; if not, [hSpriteIndexOrTextID] is set to 0 -IsSpriteOrSignInFrontOfPlayer:: ; 0b23 (0:0b23) - xor a - ld [hSpriteIndexOrTextID],a - ld a,[wd4b0] ; number of signs in the map - and a - jr z,.extendRangeOverCounter -; if there are signs - predef GetTileAndCoordsInFrontOfPlayer ; get the coordinates in front of the player in de - ld hl,wd4b1 ; start of sign coordinates - ld a,[wd4b0] ; number of signs in the map - ld b,a - ld c,$00 -.signLoop - inc c - ld a,[hli] ; sign Y - cp d - jr z,.yCoordMatched - inc hl - jr .retry -.yCoordMatched - ld a,[hli] ; sign X - cp e - jr nz,.retry -.xCoordMatched -; found sign - push hl - push bc - ld hl,wd4d1 ; start of sign text ID's - ld b,$00 - dec c - add hl,bc - ld a,[hl] - ld [hSpriteIndexOrTextID],a ; store sign text ID - pop bc - pop hl - ret -.retry - dec b - jr nz,.signLoop -; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC -.extendRangeOverCounter - predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player in c - ld hl,W_TILESETTALKINGOVERTILES ; list of tiles that extend talking range (counter tiles) - ld b,$03 - ld d,$20 ; talking range in pixels (long range) -.counterTilesLoop - ld a,[hli] - cp c - jr z,IsSpriteInFrontOfPlayer2 ; jumps if the tile in front of the player is a counter tile - dec b - jr nz,.counterTilesLoop - -; part of the above function, but sometimes its called on its own, when signs are irrelevant -; the caller must zero [hSpriteIndexOrTextID] -IsSpriteInFrontOfPlayer:: ; 0b6b (0:0b6b) - ld d,$10 ; talking range in pixels (normal range) -IsSpriteInFrontOfPlayer2:: ; 0b6d (0:0b6d) - ld bc,$3c40 ; Y and X position of player sprite - ld a,[wSpriteStateData1 + 9] ; direction the player is facing -.checkIfPlayerFacingUp - cp a,$04 - jr nz,.checkIfPlayerFacingDown -; facing up - ld a,b - sub d - ld b,a - ld a,$08 - jr .doneCheckingDirection -.checkIfPlayerFacingDown - cp a,$00 - jr nz,.checkIfPlayerFacingRight -; facing down - ld a,b - add d - ld b,a - ld a,$04 - jr .doneCheckingDirection -.checkIfPlayerFacingRight - cp a,$0c - jr nz,.playerFacingLeft -; facing right - ld a,c - add d - ld c,a - ld a,$01 - jr .doneCheckingDirection -.playerFacingLeft -; facing left - ld a,c - sub d - ld c,a - ld a,$02 -.doneCheckingDirection - ld [wd52a],a - ld a,[W_NUMSPRITES] ; number of sprites - and a - ret z -; if there are sprites - ld hl,wSpriteStateData1 + $10 - ld d,a - ld e,$01 -.spriteLoop - push hl - ld a,[hli] ; image (0 if no sprite) - and a - jr z,.nextSprite - inc l - ld a,[hli] ; sprite visibility - inc a - jr z,.nextSprite - inc l - ld a,[hli] ; Y location - cp b - jr nz,.nextSprite - inc l - ld a,[hl] ; X location - cp c - jr z,.foundSpriteInFrontOfPlayer -.nextSprite - pop hl - ld a,l - add a,$10 - ld l,a - inc e - dec d - jr nz,.spriteLoop - ret -.foundSpriteInFrontOfPlayer - pop hl - ld a,l - and a,$f0 - inc a - ld l,a - set 7,[hl] - ld a,e - ld [hSpriteIndexOrTextID],a - ret - -; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing) -; sets the carry flag if there is a collision, and unsets it if there isn't a collision -CollisionCheckOnLand:: ; 0bd1 (0:0bd1) - ld a,[wd736] - bit 6,a ; is the player jumping? - jr nz,.noCollision -; if not jumping a ledge - ld a,[wSimulatedJoypadStatesIndex] - and a - jr nz,.noCollision ; no collisions when the player's movements are being controlled by the game - ld a,[wd52a] ; the direction that the player is trying to go in - ld d,a - ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code) - and d ; check if a sprite is in the direction the player is trying to go - jr nz,.collision - xor a - ld [hSpriteIndexOrTextID],a - call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision? - ld a,[hSpriteIndexOrTextID] - and a ; was there a sprite collision? - jr nz,.collision -; if no sprite collision - ld hl,TilePairCollisionsLand - call CheckForJumpingAndTilePairCollisions - jr c,.collision - call CheckTilePassable - jr nc,.noCollision -.collision - ld a,[wc02a] - cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing - jr z,.setCarry - ld a,(SFX_02_5b - SFX_Headers_02) / 3 - call PlaySound ; play collision sound (if it's not already playing) -.setCarry - scf - ret -.noCollision - and a - ret - -; function that checks if the tile in front of the player is passable -; clears carry if it is, sets carry if not -CheckTilePassable:: ; 0c10 (0:0c10) - predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player - ld a,[wTileInFrontOfPlayer] ; tile in front of player - ld c,a - 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 -.loop - ld a,[hli] - cp a,$ff - jr z,.tileNotPassable - cp c - ret z - jr .loop -.tileNotPassable - scf - ret - -; check if the player is going to jump down a small ledge -; and check for collisions that only occur between certain pairs of tiles -; Input: hl - address of directional collision data -; sets carry if there is a collision and unsets carry if not -CheckForJumpingAndTilePairCollisions:: ; 0c2a (0:0c2a) - push hl - predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player - push de - push bc - callba HandleLedges ; check if the player is trying to jump a ledge - pop bc - pop de - pop hl - and a - ld a,[wd736] - bit 6,a ; is the player jumping? - ret nz -; if not jumping - -CheckForTilePairCollisions2:: ; 0c44 (0:0c44) - aCoord 8, 9 ; tile the player is on - ld [wcf0e],a - -CheckForTilePairCollisions:: ; 0c4a (0:0c4a) - ld a,[wTileInFrontOfPlayer] - ld c,a -.tilePairCollisionLoop - ld a,[W_CURMAPTILESET] ; tileset number - ld b,a - ld a,[hli] - cp a,$ff - jr z,.noMatch - cp b - jr z,.tilesetMatches - inc hl -.retry - inc hl - jr .tilePairCollisionLoop -.tilesetMatches - ld a,[wcf0e] ; tile the player is on - ld b,a - ld a,[hl] - cp b - jr z,.currentTileMatchesFirstInPair - inc hl - ld a,[hl] - cp b - jr z,.currentTileMatchesSecondInPair - jr .retry -.currentTileMatchesFirstInPair - inc hl - ld a,[hl] - cp c - jr z,.foundMatch - jr .tilePairCollisionLoop -.currentTileMatchesSecondInPair - dec hl - ld a,[hli] - cp c - inc hl - jr nz,.tilePairCollisionLoop -.foundMatch - scf - ret -.noMatch - and a - ret - -; FORMAT: tileset number, tile 1, tile 2 -; terminated by 0xFF -; these entries indicate that the player may not cross between tile 1 and tile 2 -; it's mainly used to simulate differences in elevation - -TilePairCollisionsLand:: ; 0c7e (0:0c7e) - db CAVERN, $20, $05 - db CAVERN, $41, $05 - db FOREST, $30, $2E - db CAVERN, $2A, $05 - db CAVERN, $05, $21 - db FOREST, $52, $2E - db FOREST, $55, $2E - db FOREST, $56, $2E - db FOREST, $20, $2E - db FOREST, $5E, $2E - db FOREST, $5F, $2E - db $FF - -TilePairCollisionsWater:: ; 0ca0 (0:0ca0) - db FOREST, $14, $2E - db FOREST, $48, $2E - db CAVERN, $14, $05 - db $FF - -; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character -LoadCurrentMapView:: ; 0caa (0:0caa) - ld a,[H_LOADEDROMBANK] - push af - ld a,[W_TILESETBANK] ; tile data ROM bank - ld [H_LOADEDROMBANK],a - ld [$2000],a ; switch to ROM bank that contains tile data - ld a,[wCurrentTileBlockMapViewPointer] ; address of upper left corner of current map view - ld e,a - ld a,[wCurrentTileBlockMapViewPointer + 1] - ld d,a - ld hl,wTileMapBackup - ld b,$05 -.rowLoop ; each loop iteration fills in one row of tile blocks - push hl - push de - ld c,$06 -.rowInnerLoop ; loop to draw each tile block of the current row - push bc - push de - push hl - ld a,[de] - ld c,a ; tile block number - call DrawTileBlock - pop hl - pop de - pop bc - inc hl - inc hl - inc hl - inc hl - inc de - dec c - jr nz,.rowInnerLoop -; update tile block map pointer to next row's address - pop de - ld a,[W_CURMAPWIDTH] - add a,$06 - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry -; update tile map pointer to next row's address - pop hl - ld a,$60 - add l - ld l,a - jr nc,.noCarry2 - inc h -.noCarry2 - dec b - jr nz,.rowLoop - ld hl,wTileMapBackup - ld bc,$0000 -.adjustForYCoordWithinTileBlock - ld a,[W_YBLOCKCOORD] - and a - jr z,.adjustForXCoordWithinTileBlock - ld bc,$0030 - add hl,bc -.adjustForXCoordWithinTileBlock - ld a,[W_XBLOCKCOORD] - and a - jr z,.copyToVisibleAreaBuffer - ld bc,$0002 - add hl,bc -.copyToVisibleAreaBuffer - ld de,wTileMap ; base address for the tiles that are directly transfered to VRAM during V-blank - ld b,$12 -.rowLoop2 - ld c,$14 -.rowInnerLoop2 - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.rowInnerLoop2 - ld a,$04 - add l - ld l,a - jr nc,.noCarry3 - inc h -.noCarry3 - dec b - jr nz,.rowLoop2 - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a ; restore previous ROM bank - ret - -AdvancePlayerSprite:: ; 0b7f (0:0b7f) - ld a,[wUpdateSpritesEnabled] - push af - ld a,$FF - ld [wUpdateSpritesEnabled],a - ld hl, _AdvancePlayerSorite ; 3c:410c - ld b, BANK(_AdvancePlayerSprite) - call Bankswitch - pop af - ld [wUpdateSpritesEnabled],a - ret - -; the following four functions are used to move the pointer to the upper left -; corner of the tile block map in the direction of motion - -MoveTileBlockMapPointerEast:: ; 0e65 (0:0e65) - ld a,[de] - add a,$01 - ld [de],a - ret nc - inc de - ld a,[de] - inc a - ld [de],a - ret - -MoveTileBlockMapPointerWest:: ; 0e6f (0:0e6f) - ld a,[de] - sub a,$01 - ld [de],a - ret nc - inc de - ld a,[de] - dec a - ld [de],a - ret - -MoveTileBlockMapPointerSouth:: ; 0e79 (0:0e79) - add a,$06 - ld b,a - ld a,[de] - add b - ld [de],a - ret nc - inc de - ld a,[de] - inc a - ld [de],a - ret - -MoveTileBlockMapPointerNorth:: ; 0e85 (0:0e85) - add a,$06 - ld b,a - ld a,[de] - sub b - ld [de],a - ret nc - inc de - ld a,[de] - dec a - ld [de],a - ret - -; the following 6 functions are used to tell the V-blank handler to redraw -; the portion of the map that was newly exposed due to the player's movement - -ScheduleNorthRowRedraw:: ; 0e91 (0:0e91) - hlCoord 0, 0 - call CopyToScreenEdgeTiles - ld a,[wMapViewVRAMPointer] - ld [H_SCREENEDGEREDRAWADDR],a - ld a,[wMapViewVRAMPointer + 1] - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,REDRAWROW - ld [H_SCREENEDGEREDRAW],a - ret - -CopyToScreenEdgeTiles:: ; 0ea6 (0:0ea6) - ld de,wScreenEdgeTiles - ld c,2 * 20 -.loop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.loop - ret - -ScheduleSouthRowRedraw:: ; 0eb2 (0:0eb2) - hlCoord 0, 16 - call CopyToScreenEdgeTiles - ld a,[wMapViewVRAMPointer] - ld l,a - ld a,[wMapViewVRAMPointer + 1] - ld h,a - ld bc,$0200 - add hl,bc - ld a,h - and a,$03 - or a,$98 - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,l - ld [H_SCREENEDGEREDRAWADDR],a - ld a,REDRAWROW - ld [H_SCREENEDGEREDRAW],a - ret - -ScheduleEastColumnRedraw:: ; 0ed3 (0:0ed3) - hlCoord 18, 0 - call ScheduleColumnRedrawHelper - ld a,[wMapViewVRAMPointer] - ld c,a - and a,$e0 - ld b,a - ld a,c - add a,18 - and a,$1f - or b - ld [H_SCREENEDGEREDRAWADDR],a - ld a,[wMapViewVRAMPointer + 1] - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,REDRAWCOL - ld [H_SCREENEDGEREDRAW],a - ret - -ScheduleColumnRedrawHelper:: ; 0ef2 (0:0ef2) - ld de,wScreenEdgeTiles - ld c,$12 -.loop - ld a,[hli] - ld [de],a - inc de - ld a,[hl] - ld [de],a - inc de - ld a,19 - add l - ld l,a - jr nc,.noCarry - inc h -.noCarry - dec c - jr nz,.loop - ret - -ScheduleWestColumnRedraw:: ; 0f08 (0:0f08) - hlCoord 0, 0 - call ScheduleColumnRedrawHelper - ld a,[wMapViewVRAMPointer] - ld [H_SCREENEDGEREDRAWADDR],a - ld a,[wMapViewVRAMPointer + 1] - ld [H_SCREENEDGEREDRAWADDR + 1],a - ld a,REDRAWCOL - ld [H_SCREENEDGEREDRAW],a - ret - -; function to write the tiles that make up a tile block to memory -; Input: c = tile block ID, hl = destination address -DrawTileBlock:: ; 0f1d (0:0f1d) - push hl - ld a,[W_TILESETBLOCKSPTR] ; pointer to tiles - ld l,a - ld a,[W_TILESETBLOCKSPTR + 1] - ld h,a - ld a,c - swap a - ld b,a - and a,$f0 - ld c,a - ld a,b - and a,$0f - ld b,a ; bc = tile block ID * 0x10 - add hl,bc - ld d,h - ld e,l ; de = address of the tile block's tiles - pop hl - ld c,$04 ; 4 loop iterations -.loop ; each loop iteration, write 4 tile numbers - push bc - ld a,[de] - ld [hli],a - inc de - ld a,[de] - ld [hli],a - inc de - ld a,[de] - ld [hli],a - inc de - ld a,[de] - ld [hl],a - inc de - ld bc,$0015 - add hl,bc - pop bc - dec c - jr nz,.loop - ret - -; function to update joypad state and simulate button presses -JoypadOverworld:: ; 0f4d (0:0f4d) - xor a - ld [wSpriteStateData1 + 3],a - ld [wSpriteStateData1 + 5],a - call RunMapScript - call Joypad - ld a,[W_FLAGS_D733] - bit 3,a ; check if a trainer wants a challenge - jr nz,.notForcedDownwards - ld a,[W_CURMAP] - cp a,ROUTE_17 ; Cycling Road - jr nz,.notForcedDownwards - ld a,[hJoyHeld] - and a,D_DOWN | D_UP | D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON - jr nz,.notForcedDownwards - ld a,D_DOWN - ld [hJoyHeld],a ; on the cycling road, if there isn't a trainer and the player isn't pressing buttons, simulate a down press -.notForcedDownwards - ld a,[wd730] - bit 7,a - ret z -; if simulating button presses - ld a,[hJoyHeld] - ld b,a - ld a,[wOverrideSimulatedJoypadStatesMask] ; bit mask for button presses that override simulated ones - and b - ret nz ; return if the simulated button presses are overridden - ld hl,wSimulatedJoypadStatesIndex - dec [hl] - ld a,[hl] - cp a,$ff - jr z,.doneSimulating ; if the end of the simulated button presses has been reached - ld hl,wSimulatedJoypadStatesEnd - add l - ld l,a - jr nc,.noCarry - inc h -.noCarry - ld a,[hl] - ld [hJoyHeld],a ; store simulated button press in joypad state - and a - ret nz - ld [hJoyPressed],a - ld [hJoyReleased],a - ret -; if done simulating button presses -.doneSimulating - xor a - ld [wWastedByteCD3A],a - ld [wSimulatedJoypadStatesIndex],a - ld [wSimulatedJoypadStatesEnd],a - ld [wJoyIgnore],a - ld [hJoyHeld],a - ld hl,wd736 - ld a,[hl] - and a,$f8 - ld [hl],a - ld hl,wd730 - res 7,[hl] - ret - -; function to check the tile ahead to determine if the character should get on land or keep surfing -; sets carry if there is a collision and clears carry otherwise -; It seems that this function has a bug in it, but due to luck, it doesn't -; show up. After detecting a sprite collision, it jumps to the code that -; checks if the next tile is passable instead of just directly jumping to the -; "collision detected" code. However, it doesn't store the next tile in c, -; so the old value of c is used. 2429 is always called before this function, -; and 2429 always sets c to 0xF0. There is no 0xF0 background tile, so it -; is considered impassable and it is detected as a collision. -CollisionCheckOnWater:: ; 0fb7 (0:0fb7) - ld a,[wd730] - bit 7,a - jp nz,.noCollision ; return and clear carry if button presses are being simulated - ld a,[wd52a] ; the direction that the player is trying to go in - ld d,a - ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code) - and d ; check if a sprite is in the direction the player is trying to go - jr nz,.checkIfNextTileIsPassable ; bug? - ld hl,TilePairCollisionsWater - call CheckForJumpingAndTilePairCollisions - jr c,.collision - predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player (puts it in c and [wTileInFrontOfPlayer]) - ld a,[wTileInFrontOfPlayer] ; tile in front of player - cp a,$14 ; water tile - jr z,.noCollision ; keep surfing if it's a water tile - cp a,$32 ; either the left tile of the S.S. Anne boarding platform or the tile on eastern coastlines (depending on the current tileset) - jr z,.checkIfVermilionDockTileset - cp a,$48 ; tile on right on coast lines in Safari Zone - jr z,.noCollision ; keep surfing -; check if the [land] tile in front of the player is passable -.checkIfNextTileIsPassable - ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles - ld a,[hli] - ld h,[hl] - ld l,a -.loop - ld a,[hli] - cp a,$ff - jr z,.collision - cp c - jr z,.stopSurfing ; stop surfing if the tile is passable - jr .loop -.collision - ld a,[wc02a] - cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing - jr z,.setCarry - ld a,(SFX_02_5b - SFX_Headers_02) / 3 - call PlaySound ; play collision sound (if it's not already playing) -.setCarry - scf - jr .done -.noCollision - and a -.done - ret -.stopSurfing - xor a - ld [wWalkBikeSurfState],a - call LoadPlayerSpriteGraphics - call PlayDefaultMusic - jr .noCollision -.checkIfVermilionDockTileset - ld a, [W_CURMAPTILESET] ; tileset - cp SHIP_PORT ; Vermilion Dock tileset - jr nz, .noCollision ; keep surfing if it's not the boarding platform tile - jr .stopSurfing ; if it is the boarding platform tile, stop surfing - -; function to run the current map's script -RunMapScript:: ; 101b (0:101b) - push hl - push de - push bc - callba TryPushingBoulder - ld a,[wFlags_0xcd60] - bit 1,a ; play boulder dust animation - jr z,.afterBoulderEffect - callba DoBoulderDustAnimation -.afterBoulderEffect - pop bc - pop de - pop hl - call RunNPCMovementScript - ld a,[W_CURMAP] ; current map number - call SwitchToMapRomBank ; change to the ROM bank the map's data is in - ld hl,W_MAPSCRIPTPTR - ld a,[hli] - ld h,[hl] - ld l,a - ld de,.return - push de - jp [hl] ; jump to script -.return - ret - -LoadWalkingPlayerSpriteGraphics:: ; 104d (0:104d) - ld de,RedSprite ; $4180 - ld hl,vNPCSprites - jr LoadPlayerSpriteGraphicsCommon - -LoadSurfingPlayerSpriteGraphics:: ; 1055 (0:1055) - ld de,SeelSprite - ld hl,vNPCSprites - jr LoadPlayerSpriteGraphicsCommon - -LoadBikePlayerSpriteGraphics:: ; 105d (0:105d) - ld de,RedCyclingSprite - ld hl,vNPCSprites - -LoadPlayerSpriteGraphicsCommon:: ; 1063 (0:1063) - push de - push hl - ld bc,(BANK(RedSprite) << 8) + $0c - call CopyVideoData - pop hl - pop de - ld a,$c0 - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry - set 3,h - ld bc,$050c - jp CopyVideoData - -; function to load data from the map header -LoadMapHeader:: ; 107c (0:107c) - callba MarkTownVisitedAndLoadMissableObjects - ld a,[W_CURMAPTILESET] - ld [wd119],a - ld a,[W_CURMAP] - call SwitchToMapRomBank - ld a,[W_CURMAPTILESET] - ld b,a - res 7,a - ld [W_CURMAPTILESET],a - ld [$ff8b],a - bit 7,b - ret nz - ld hl,MapHeaderPointers - ld a,[W_CURMAP] - sla a - jr nc,.noCarry1 - inc h -.noCarry1 - add l - ld l,a - jr nc,.noCarry2 - inc h -.noCarry2 - ld a,[hli] - ld h,[hl] - ld l,a ; hl = base of map header -; copy the first 10 bytes (the fixed area) of the map data to D367-D370 - ld de,W_CURMAPTILESET - ld c,$0a -.copyFixedHeaderLoop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.copyFixedHeaderLoop -; initialize all the connected maps to disabled at first, before loading the actual values - ld a,$ff - ld [W_MAPCONN1PTR],a - ld [W_MAPCONN2PTR],a - ld [W_MAPCONN3PTR],a - ld [W_MAPCONN4PTR],a -; copy connection data (if any) to WRAM - ld a,[W_MAPCONNECTIONS] - ld b,a -.checkNorth - bit 3,b - jr z,.checkSouth - ld de,W_MAPCONN1PTR - call CopyMapConnectionHeader -.checkSouth - bit 2,b - jr z,.checkWest - ld de,W_MAPCONN2PTR - call CopyMapConnectionHeader -.checkWest - bit 1,b - jr z,.checkEast - ld de,W_MAPCONN3PTR - call CopyMapConnectionHeader -.checkEast - bit 0,b - jr z,.getObjectDataPointer - ld de,W_MAPCONN4PTR - call CopyMapConnectionHeader -.getObjectDataPointer - ld a,[hli] - ld [wd3a9],a - ld a,[hli] - ld [wd3aa],a - push hl - ld a,[wd3a9] - ld l,a - ld a,[wd3aa] - ld h,a ; hl = base of object data - ld de,wd3ad ; background tile ID - ld a,[hli] - ld [de],a ; save background tile ID -.loadWarpData - ld a,[hli] - ld [wNumberOfWarps],a - and a - jr z,.loadSignData - ld c,a - ld de,wWarpEntries -.warpLoop ; one warp per loop iteration - ld b,$04 -.warpInnerLoop - ld a,[hli] - ld [de],a - inc de - dec b - jr nz,.warpInnerLoop - dec c - jr nz,.warpLoop -.loadSignData - ld a,[hli] ; number of signs - ld [wd4b0],a ; save the number of signs - and a ; are there any signs? - jr z,.loadSpriteData ; if not, skip this - ld c,a - ld de,wd4d1 ; base address of sign text IDs - ld a,d - ld [$ff95],a - ld a,e - ld [$ff96],a - ld de,wd4b1 ; base address of sign coordinates -.signLoop - ld a,[hli] - ld [de],a - inc de - ld a,[hli] - ld [de],a - inc de - push de - ld a,[$ff95] - ld d,a - ld a,[$ff96] - ld e,a - ld a,[hli] - ld [de],a - inc de - ld a,d - ld [$ff95],a - ld a,e - ld [$ff96],a - pop de - dec c - jr nz,.signLoop -.loadSpriteData - ld a,[wd72e] - bit 5,a ; did a battle happen immediately before this? - jp nz,.finishUp ; if so, skip this because battles don't destroy this data - ld a,[hli] - ld [W_NUMSPRITES],a ; save the number of sprites - push hl -; zero C110-C1FF and C210-C2FF - ld hl,wSpriteStateData1 + $10 - ld de,wSpriteStateData2 + $10 - xor a - ld b,$f0 -.zeroSpriteDataLoop - ld [hli],a - ld [de],a - inc e - dec b - jr nz,.zeroSpriteDataLoop -; initialize all C100-C1FF sprite entries to disabled (other than player's) - ld hl,wSpriteStateData1 + $12 - ld de,$0010 - ld c,$0f -.disableSpriteEntriesLoop - ld [hl],$ff - add hl,de - dec c - jr nz,.disableSpriteEntriesLoop - pop hl - ld de,wSpriteStateData1 + $10 - ld a,[W_NUMSPRITES] ; number of sprites - and a ; are there any sprites? - jp z,.finishUp ; if there are no sprites, skip the rest - ld b,a - ld c,$00 -.loadSpriteLoop - ld a,[hli] - ld [de],a ; store picture ID at C1X0 - inc d - ld a,$04 - add e - ld e,a - ld a,[hli] - ld [de],a ; store Y position at C2X4 - inc e - ld a,[hli] - ld [de],a ; store X position at C2X5 - inc e - ld a,[hli] - ld [de],a ; store movement byte 1 at C2X6 - ld a,[hli] - ld [$ff8d],a ; save movement byte 2 - ld a,[hli] - ld [$ff8e],a ; save text ID and flags byte - push bc - push hl - ld b,$00 - ld hl,W_MAPSPRITEDATA - add hl,bc - ld a,[$ff8d] - ld [hli],a ; store movement byte 2 in byte 0 of sprite entry - ld a,[$ff8e] - ld [hl],a ; this appears pointless, since the value is overwritten immediately after - ld a,[$ff8e] - ld [$ff8d],a - and a,$3f - ld [hl],a ; store text ID in byte 1 of sprite entry - pop hl - ld a,[$ff8d] - bit 6,a - jr nz,.trainerSprite - bit 7,a - jr nz,.itemBallSprite - jr .regularSprite -.trainerSprite - ld a,[hli] - ld [$ff8d],a ; save trainer class - ld a,[hli] - ld [$ff8e],a ; save trainer number (within class) - push hl - ld hl,W_MAPSPRITEEXTRADATA - add hl,bc - ld a,[$ff8d] - ld [hli],a ; store trainer class in byte 0 of the entry - ld a,[$ff8e] - ld [hl],a ; store trainer number in byte 1 of the entry - pop hl - jr .nextSprite -.itemBallSprite - ld a,[hli] - ld [$ff8d],a ; save item number - push hl - ld hl,W_MAPSPRITEEXTRADATA - add hl,bc - ld a,[$ff8d] - ld [hli],a ; store item number in byte 0 of the entry - xor a - ld [hl],a ; zero byte 1, since it is not used - pop hl - jr .nextSprite -.regularSprite - push hl - ld hl,W_MAPSPRITEEXTRADATA - add hl,bc -; zero both bytes, since regular sprites don't use this extra space - xor a - ld [hli],a - ld [hl],a - pop hl -.nextSprite - pop bc - dec d - ld a,$0a - add e - ld e,a - inc c - inc c - dec b - jp nz,.loadSpriteLoop -.finishUp - predef LoadTilesetHeader - callab LoadWildData - pop hl ; restore hl from before going to the warp/sign/sprite data (this value was saved for seemingly no purpose) - ld a,[W_CURMAPHEIGHT] ; map height in 4x4 tile blocks - add a ; double it - ld [wd524],a ; store map height in 2x2 tile blocks - ld a,[W_CURMAPWIDTH] ; map width in 4x4 tile blocks - add a ; double it - ld [wd525],a ; map width in 2x2 tile blocks - ld a,[W_CURMAP] - ld c,a - ld b,$00 - ld a,[H_LOADEDROMBANK] - push af - ld a, BANK(MapSongBanks) - ld [H_LOADEDROMBANK],a - ld [$2000],a - ld hl, MapSongBanks - add hl,bc - add hl,bc - ld a,[hli] - ld [wd35b],a ; music 1 - ld a,[hl] - ld [wd35c],a ; music 2 - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; function to copy map connection data from ROM to WRAM -; Input: hl = source, de = destination -CopyMapConnectionHeader:: ; 1238 (0:1238) - ld c,$0b -.loop - ld a,[hli] - ld [de],a - inc de - dec c - jr nz,.loop - ret - -; function to load map data -LoadMapData:: ; 1241 (0:1241) - ld a,[H_LOADEDROMBANK] - push af - call DisableLCD - ld a,$98 - ld [wMapViewVRAMPointer + 1],a - xor a - ld [wMapViewVRAMPointer],a - ld [hSCY],a - ld [hSCX],a - ld [wWalkCounter],a - ld [wd119],a - ld [wWalkBikeSurfStateCopy],a - ld [W_SPRITESETID],a - call LoadTextBoxTilePatterns - call LoadMapHeader - callba InitMapSprites ; load tile pattern data for sprites - call LoadTileBlockMap - call LoadTilesetTilePatternData - call LoadCurrentMapView -; copy current map view to VRAM - ld hl,wTileMap - ld de,vBGMap0 - ld b,18 -.vramCopyLoop - ld c,20 -.vramCopyInnerLoop - ld a,[hli] - ld [de],a - inc e - dec c - jr nz,.vramCopyInnerLoop - ld a,32 - 20 - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry - dec b - jr nz,.vramCopyLoop - ld a,$01 - ld [wUpdateSpritesEnabled],a - call EnableLCD - ld b,$09 - call GoPAL_SET - call LoadPlayerSpriteGraphics - ld a,[wd732] - and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp - jr nz,.restoreRomBank - ld a,[W_FLAGS_D733] - bit 1,a - jr nz,.restoreRomBank - call Func_235f ; music related - call Func_2312 ; music related -.restoreRomBank - pop af - ld [H_LOADEDROMBANK],a - ld [$2000],a - ret - -; function to switch to the ROM bank that a map is stored in -; Input: a = map number -SwitchToMapRomBank:: ; 12bc (0:12bc) - push hl - push bc - ld c,a - ld b,$00 - ld a,Bank(MapHeaderBanks) - call BankswitchHome ; switch to ROM bank 3 - ld hl,MapHeaderBanks - add hl,bc - ld a,[hl] - ld [$ffe8],a ; save map ROM bank - call BankswitchBack - ld a,[$ffe8] - ld [H_LOADEDROMBANK],a - ld [$2000],a ; switch to map ROM bank - pop bc - pop hl - ret - -IgnoreInputForHalfSecond: ; 12da (0:12da) - ld a, 30 - ld [wIgnoreInputCounter], a - ld hl, wd730 - ld a, [hl] - or $26 - ld [hl], a ; set ignore input bit - ret - -ResetUsingStrengthOutOfBattleBit: ; 12e7 (0:12e7) - ld hl, wd728 - res 0, [hl] - ret - -ForceBikeOrSurf:: ; 12ed (0:12ed) - ld b, BANK(RedSprite) - ld hl, LoadPlayerSpriteGraphics - call Bankswitch - jp PlayDefaultMusic ; update map/player state? - -; Handle the player jumping down -; a ledge in the overworld. -HandleMidJump:: ; 0fe1 (0:0fe1) - ld a,[wd736] - bit 7,a ; jumping down a ledge? - ret z - ld b, BANK(_HandleMidJump) - ld hl, _HandleMidJump - jp Bankswitch - -IsSpinning:: ; 0ff0 (0:0ff0) - ld a,[wd736] - bit 7,a - ret z ; no spinning - ld b, BANK(LoadSpinnerArrowTiles); spin while moving - ld hl,LoadSpinnerArrowTiles ; 11:5077 - jp Bankswitch - -Func_0ffe:: ; 0ffe (0:0ffe) - ld hl, Func_fcf0c ; 3f:4f0c - ld b, BANK(Func_fcf0c) - jp Bankswitch +EnterMap:: ; 01d7 (0:01d7)
+; Load a new map.
+ ld a, $ff
+ ld [wJoyIgnore], a
+ call LoadMapData
+ callba ClearVariablesAfterLoadingMapData
+ ld hl, wd72c
+ bit 0, [hl] ; has the player already made 3 steps since the last battle?
+ jr z, .skipGivingThreeStepsOfNoRandomBattles
+ ld a, 3 ; minimum number of steps between battles
+ ld [wNumberOfNoRandomBattleStepsLeft], a
+.skipGivingThreeStepsOfNoRandomBattles
+ ld hl, wd72e
+ bit 5, [hl] ; did a battle happen immediately before this?
+ res 5, [hl] ; unset the "battle just happened" flag
+ call z, ResetUsingStrengthOutOfBattleBit
+ call nz, MapEntryAfterBattle
+ ld hl, wd732
+ ld a, [hl]
+ and 1 << 4 | 1 << 3 ; fly warp or dungeon warp
+ jr z, .didNotEnterUsingFlyWarpOrDungeonWarp
+ callba EnterMapAnim
+ call UpdateSprites
+ ld hl, wd732
+ res 3, [hl]
+ ld hl, wd72e
+ res 4, [hl]
+ call Func_342a
+.didNotEnterUsingFlyWarpOrDungeonWarp
+ callba CheckForceBikeOrSurf ; handle currents in SF islands and forced bike riding in cycling road
+ ld hl, wd732
+ bit 4, [hl]
+ res 4, [hl]
+ ld hl, wd72d
+ res 5, [hl]
+ call UpdateSprites
+ ld hl, wd126
+ set 5, [hl]
+ set 6, [hl]
+ xor a
+ ld [wJoyIgnore], a
+
+OverworldLoop:: ; 0242 (0:0242)
+ call DelayFrame
+OverworldLoopLessDelay:: ; 0245 (0:0245)
+ call DelayFrame
+ call Func_342a
+ call LoadGBPal
+ ld a,[wWalkCounter]
+ and a
+ jp nz,.moveAhead ; if the player sprite has not yet completed the walking animation
+ call JoypadOverworld ; get joypad state (which is possibly simulated)
+ callba SafariZoneCheck
+ ld a,[wSafariZoneGameOver]
+ and a
+ jp nz,WarpFound2
+ ld hl,wd72d
+ bit 3,[hl]
+ res 3,[hl]
+ jp nz,WarpFound2
+ ld a,[wd732]
+ and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp
+ jp nz,HandleFlyWarpOrDungeonWarp
+ ld a,[W_CUROPPONENT]
+ and a
+ jp nz,.newBattle
+ ld a,[wd730]
+ bit 7,a ; are we simulating button presses?
+ jr z,.notSimulating
+ ld a,[hJoyHeld]
+ jr .checkIfStartIsPressed
+.notSimulating
+ ld a,[hJoyPressed]
+.checkIfStartIsPressed
+ bit 3,a ; start button
+ jr z,.startButtonNotPressed
+; if START is pressed
+ xor a
+ ld [hSpriteIndexOrTextID],a ; start menu text ID
+ jp .displayDialogue
+.startButtonNotPressed
+ bit 0,a ; A button
+ jp z,.checkIfDownButtonIsPressed
+; if A is pressed
+ ld a,[wd730]
+ bit 2,a
+ jp nz,.noDirectionButtonsPressed
+ call IsPlayerCharacterBeingControlledByGame
+ jr nz,.checkForOpponent
+ call CheckForHiddenObjectOrBookshelfOrCardKeyDoor
+ ld a,[$ffeb]
+ and a
+ jp z,OverworldLoop ; jump if a hidden object or bookshelf was found, but not if a card key door was found
+ xor a
+ ld [wd436],a ; new yellow address
+ call IsSpriteOrSignInFrontOfPlayer
+ call Func_0ffe
+ ld a,[hSpriteIndexOrTextID]
+ and a
+ jp z,OverworldLoop
+.displayDialogue
+ predef GetTileAndCoordsInFrontOfPlayer
+ call UpdateSprites
+ ld a,[wFlags_0xcd60]
+ bit 2,a
+ jr nz,.checkForOpponent
+ bit 0,a
+ jr nz,.checkForOpponent
+ aCoord 8, 9
+ ld [wcf0e],a
+ call DisplayTextID ; display either the start menu or the NPC/sign text
+ ld a,[wcc47]
+ and a
+ jr z,.checkForOpponent
+ xor a
+ ld [wcc47],a
+ jp EnterMap
+; predef LoadSAV
+; ld a,[W_CURMAP]
+; ld [wDestinationMap],a
+; call SpecialWarpIn
+; ld a,[W_CURMAP]
+; call SwitchToMapRomBank ; switch to the ROM bank of the current map
+; ld hl,W_CURMAPTILESET
+; set 7,[hl]
+.checkForOpponent
+ ld a,[W_CUROPPONENT]
+ and a
+ jp nz,.newBattle
+ jp OverworldLoop
+.noDirectionButtonsPressed
+ call UpdateSprites ; 231c
+ ld hl,wFlags_0xcd60
+ res 2,[hl]
+ xor a
+ ld [wd435], a
+ ld a, $1
+ ld a,$01
+ ld [wcc4b],a
+ ld a,[wd528] ; the direction that was pressed last time
+ and a
+ jr z, .overworldloop
+; if a direction was pressed last time
+ ld [wd529],a ; save the last direction
+ xor a
+ ld [wd528],a ; zero the direction
+.overworldloop
+ jp OverworldLoop
+.checkIfDownButtonIsPressed
+ ld a,[hJoyHeld] ; current joypad state
+ bit 7,a ; down button
+ jr z,.checkIfUpButtonIsPressed
+ ld a,$01
+ ld [wSpriteStateData1 + 3],a
+ ld a,$04
+ jr .handleDirectionButtonPress
+.checkIfUpButtonIsPressed
+ bit 6,a ; up button
+ jr z,.checkIfLeftButtonIsPressed
+ ld a,$ff
+ ld [wSpriteStateData1 + 3],a
+ ld a,$08
+ jr .handleDirectionButtonPress
+.checkIfLeftButtonIsPressed
+ bit 5,a ; left button
+ jr z,.checkIfRightButtonIsPressed
+ ld a,$ff
+ ld [wSpriteStateData1 + 5],a
+ ld a,$02
+ jr .handleDirectionButtonPress
+.checkIfRightButtonIsPressed
+ bit 4,a ; right button
+ jr z,.noDirectionButtonsPressed
+ ld a,$01
+ ld [wSpriteStateData1 + 5],a
+.handleDirectionButtonPress
+ ld [wd52a],a ; new direction
+ ld a,[wd730]
+ bit 7,a ; are we simulating button presses?
+ jr nz,.noDirectionChange ; ignore direction changes if we are
+ ld a,[wcc4b]
+ and a
+ jr z,.noDirectionChange
+ ld a,[wd52a] ; new direction
+ ld b,a
+ ld a,[wd529] ; old direction
+ cp b
+ jr z,.noDirectionChange
+ ld a,$8
+ ld [wd434],a
+; unlike in red/blue, yellow does not have the 180 degrees odd code
+ ld hl,wFlags_0xcd60
+ set 2,[hl]
+ xor a
+ ld [wcc4b],a
+ ld a,[wd52a]
+ ld [wd528],a
+ call NewBattle
+ jp c,.battleOccurred
+ jp OverworldLoop
+.noDirectionChange
+ ld a,[wd52a] ; current direction
+ ld [wd528],a ; save direction
+ call UpdateSprites
+ ld a,[wWalkBikeSurfState]
+ cp a,$02 ; surfing
+ jr z,.surfing
+; not surfing
+ call CollisionCheckOnLand
+ jr nc,.noCollision
+; collision occurred
+ push hl
+ ld hl,wd736
+ bit 2,[hl] ; standing on warp flag
+ pop hl
+ jp z,OverworldLoop
+; collision occurred while standing on a warp
+ push hl
+ call ExtraWarpCheck ; sets carry if there is a potential to warp
+ pop hl
+ jp c,CheckWarpsCollision
+ jp OverworldLoop
+.surfing
+ call CollisionCheckOnWater
+ jp c,OverworldLoop
+.noCollision
+ ld a,$08
+ ld [wWalkCounter],a
+ callab Func_fcc08
+ jr .moveAhead2
+.moveAhead
+ call IsSpinning
+ call UpdateSprites ; move sprites
+.moveAhead2
+ ld hl,wFlags_0xcd60
+ res 2,[hl]
+ xor a
+ ld [wd435],a
+ call DoBikeSpeedup
+ call AdvancePlayerSprite
+ ld a,[wWalkCounter]
+ and a
+ jp nz,CheckMapConnections ; it seems like this check will never succeed (the other place where CheckMapConnections is run works)
+; walking animation finished
+ call StepCountCheck
+ ld a,[wd790]
+ bit 7,a ; in the safari zone?
+ jr z,.notSafariZone
+ callba SafariZoneCheckSteps
+ ld a,[wSafariZoneGameOver]
+ and a
+ jp nz,WarpFound2
+.notSafariZone
+ ld a,[W_ISINBATTLE]
+ and a
+ jp nz,CheckWarpsNoCollision
+ predef ApplyOutOfBattlePoisonDamage ; also increment daycare mon exp
+ ld a,[wd12d]
+ and a
+ jp nz,HandleBlackOut ; if all pokemon fainted
+.newBattle
+ call NewBattle
+ ld hl,wd736
+ res 2,[hl] ; standing on warp flag
+ jp nc,CheckWarpsNoCollision ; check for warps if there was no battle
+.battleOccurred
+ ld hl,wd72d
+ res 6,[hl]
+ ld hl,W_FLAGS_D733
+ res 3,[hl]
+ ld hl,wd126
+ set 5,[hl]
+ set 6,[hl]
+ xor a
+ ld [hJoyHeld],a
+ ld a,[W_CURMAP]
+ cp a,CINNABAR_GYM
+ jr nz,.notCinnabarGym
+ ld hl,wd79b
+ set 7,[hl]
+.notCinnabarGym
+ ld hl,wd72e
+ set 5,[hl]
+ ld a,[W_CURMAP]
+ cp a,OAKS_LAB
+ jp z,.noFaintCheck ; no blacking out if the player lost to the rival in Oak's lab
+ callab AnyPartyAlive
+ ld a,d
+ and a
+ jr z,.allPokemonFainted
+.noFaintCheck
+ ld c,$0a
+ call DelayFrames
+ jp EnterMap
+;.allPokemonFainted
+; ld a,$ff
+; ld [W_ISINBATTLE],a
+; call RunMapScript
+; jp HandleBlackOut
+
+StepCountCheck:: ; 0457 (0:0457)
+ ld a,[wd730]
+ bit 7,a
+ jr nz,.doneStepCounting ; if button presses are being simulated, don't count steps
+; step counting
+ ld hl,wStepCounter
+ dec [hl]
+ ld a,[wd72c]
+ bit 0,a
+ jr z,.doneStepCounting
+ ld hl,wNumberOfNoRandomBattleStepsLeft
+ dec [hl]
+ jr nz,.doneStepCounting
+ ld hl,wd72c
+ res 0,[hl] ; indicate that the player has stepped thrice since the last battle
+.doneStepCounting
+ ret
+
+; function to determine if there will be a battle and execute it (either a trainer battle or wild battle)
+; sets carry if a battle occurred and unsets carry if not
+NewBattle:: ; 0480 (0:0480)
+ ld a,[wd72d]
+ bit 4,a
+ jr nz,.noBattle
+ call IsPlayerCharacterBeingControlledByGame
+ jr nz,.noBattle ; no battle if the player character is under the game's control
+ ld a,[wd72e]
+ bit 4,a
+ jr nz,.noBattle
+ ld b, BANK(InitBattle)
+ ld hl, InitBattle ; 3d:5ff2
+ jp Bankswitch
+.noBattle
+ and a
+ ret
+
+DoBikeSpeedup:: ; 049d (0:049d)
+ ld a,[wWalkBikeSurfState]
+ dec a ; riding a bike?
+ ret nz
+ ld a,[wd736]
+ bit 6,a
+ ret nz
+ ld a,[wNPCMovementScriptPointerTableNum]
+ and a
+ ret nz
+ ld a,[W_CURMAP]
+ cp ROUTE_17 ; cycling road
+ jr nz,.goFaster
+ ld a,[hJoyHeld]
+ and a,D_UP | D_LEFT | D_RIGHT
+ ret nz
+.goFaster
+ call AdvancePlayerSprite
+ ret
+
+; check if the player has stepped onto a warp after having not collided
+CheckWarpsNoCollision:: ; 04bd (0:04bd)
+ ld a,[wNumberOfWarps]
+ and a
+ jp z,CheckMapConnections
+ ld b,0
+ ld a,[wNumberOfWarps]
+ ld c,a
+ ld a,[W_YCOORD]
+ ld d,a
+ ld a,[W_XCOORD]
+ ld e,a
+ ld hl,wWarpEntries
+CheckWarpsNoCollisionLoop:: ; 04d5 (0:04d5)
+ ld a,[hli] ; check if the warp's Y position matches
+ cp d
+ jr nz,CheckWarpsNoCollisionRetry1
+ ld a,[hli] ; check if the warp's X position matches
+ cp e
+ jr nz,CheckWarpsNoCollisionRetry2
+; if a match was found
+ push hl
+ push bc
+ ld hl,wd736
+ set 2,[hl] ; standing on warp flag
+ callba IsPlayerStandingOnDoorTileOrWarpTile
+ pop bc
+ pop hl
+ jr c,WarpFound1 ; jump if standing on door or warp
+ push hl
+ push bc
+ call ExtraWarpCheck
+ pop bc
+ pop hl
+ jr nc,CheckWarpsNoCollisionRetry2
+; if the extra check passed
+ ld a,[W_FLAGS_D733]
+ bit 2,a
+ jr nz,WarpFound1
+ push de
+ push bc
+ call Joypad
+ pop bc
+ pop de
+ ld a,[hJoyHeld]
+ and a,D_DOWN | D_UP | D_LEFT | D_RIGHT
+ jr z,CheckWarpsNoCollisionRetry2 ; if directional buttons aren't being pressed, do not pass through the warp
+ jr WarpFound1
+
+CheckWarpsNoCollisionRetry1:: ; 050f (0:050f)
+ inc hl
+CheckWarpsNoCollisionRetry2:: ; 0510 (0:0510)
+ inc hl
+ inc hl
+ContinueCheckWarpsNoCollisionLoop:: ; 0512 (0:0512)
+ inc b ; increment warp number
+ dec c ; decrement number of warps
+ jp nz,CheckWarpsNoCollisionLoop
+ jp CheckMapConnections
+
+; check if the player has stepped onto a warp after having collided
+CheckWarpsCollision:: ; 051a (0:051a)
+ ld a,[wNumberOfWarps]
+ ld c,a
+ ld hl,wWarpEntries
+.loop
+ ld a,[hli] ; Y coordinate of warp
+ ld b,a
+ ld a,[W_YCOORD]
+ cp b
+ jr nz,.retry1
+ ld a,[hli] ; X coordinate of warp
+ ld b,a
+ ld a,[W_XCOORD]
+ cp b
+ jr nz,.retry2
+ ld a,[hli]
+ ld [wDestinationWarpID],a
+ ld a,[hl]
+ ld [$ff8b],a ; save target map
+ jr WarpFound2
+.retry1
+ inc hl
+.retry2
+ inc hl
+ inc hl
+ dec c
+ jr nz,.loop
+ jp OverworldLoop
+
+WarpFound1:: ; 0543 (0:0543)
+ ld a,[hli]
+ ld [wDestinationWarpID],a
+ ld a,[hli]
+ ld [$ff8b],a ; save target map
+
+WarpFound2:: ; 054a (0:054a)
+ ld a,[wNumberOfWarps]
+ sub c
+ ld [wd73b],a ; save ID of used warp
+ ld a,[W_CURMAP]
+ ld [wd73c],a
+ call CheckIfInOutsideMap
+ jr nz,.indoorMaps
+; this is for handling "outside" maps that can't have the 0xFF destination map
+ ld a,[W_CURMAP]
+ ld [wLastMap],a
+ ld a,[W_CURMAPWIDTH]
+ ld [wd366],a
+ ld a,[$ff8b] ; destination map number
+ ld [W_CURMAP],a ; change current map to destination map
+ cp a,ROCK_TUNNEL_1
+ jr nz,.notRockTunnel
+ ld a,$06
+ ld [wMapPalOffset],a
+ call GBFadeOutToBlack
+.notRockTunnel
+ callab Func_fc5fa ; 3f:45fa
+ call PlayMapChangeSound
+ jr .done
+; for maps that can have the 0xFF destination map, which means to return to the outside map; not all these maps are necessarily indoors, though
+.indoorMaps
+ ld a,[$ff8b] ; destination map
+ cp a,$ff
+ jr z,.goBackOutside
+; if not going back to the previous map
+ ld [W_CURMAP],a ; current map number
+ callba IsPlayerStandingOnWarpPadOrHole
+ ld a,[wcd5b]
+ dec a ; is the player on a warp pad?
+ jr nz,.notWarpPad
+; if the player is on a warp pad
+ call LeaveMapAnim
+ ld hl,wd732
+ set 3,[hl]
+ jr .skipMapChangeSound
+.notWarpPad
+ call PlayMapChangeSound
+.skipMapChangeSound
+ ld hl,wd736
+ res 0,[hl]
+ res 1,[hl]
+ callab Func_fc65b ; 3f:465b
+ jr .done
+.goBackOutside
+ callab Func_fc69a ; 3f:469a
+ ld a,[wLastMap]
+ ld [W_CURMAP],a
+ call PlayMapChangeSound
+ xor a
+ ld [wMapPalOffset],a
+.done
+ ld hl,wd736
+ set 0,[hl] ; have the player's sprite step out from the door (if there is one)
+ call IgnoreInputForHalfSecond
+ jp EnterMap
+
+; if no matching warp was found
+CheckMapConnections:: ; 05db (0:05db)
+.checkWestMap
+ ld a,[W_XCOORD]
+ cp a,$ff
+ jr nz,.checkEastMap
+ ld a,[W_MAPCONN3PTR]
+ ld [W_CURMAP],a
+ ld a,[wd38f] ; new X coordinate upon entering west map
+ ld [W_XCOORD],a
+ ld a,[W_YCOORD]
+ ld c,a
+ ld a,[wd38e] ; Y adjustment upon entering west map
+ add c
+ ld c,a
+ ld [W_YCOORD],a
+ ld a,[wd390] ; pointer to upper left corner of map without adjustment for Y position
+ ld l,a
+ ld a,[wd391]
+ ld h,a
+ srl c
+ jr z,.savePointer1
+.pointerAdjustmentLoop1
+ ld a,[wd38d] ; width of connected map
+ add a,$06
+ ld e,a
+ ld d,$00
+ ld b,$00
+ add hl,de
+ dec c
+ jr nz,.pointerAdjustmentLoop1
+.savePointer1
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+ jp .loadNewMap
+.checkEastMap
+ ld b,a
+ ld a,[wd525] ; map width
+ cp b
+ jr nz,.checkNorthMap
+ ld a,[W_MAPCONN4PTR]
+ ld [W_CURMAP],a
+ ld a,[wd39a] ; new X coordinate upon entering east map
+ ld [W_XCOORD],a
+ ld a,[W_YCOORD]
+ ld c,a
+ ld a,[wd399] ; Y adjustment upon entering east map
+ add c
+ ld c,a
+ ld [W_YCOORD],a
+ ld a,[wd39b] ; pointer to upper left corner of map without adjustment for Y position
+ ld l,a
+ ld a,[wd39c]
+ ld h,a
+ srl c
+ jr z,.savePointer2
+.pointerAdjustmentLoop2
+ ld a,[wd398]
+ add a,$06
+ ld e,a
+ ld d,$00
+ ld b,$00
+ add hl,de
+ dec c
+ jr nz,.pointerAdjustmentLoop2
+.savePointer2
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+ jp .loadNewMap
+.checkNorthMap
+ ld a,[W_YCOORD]
+ cp a,$ff
+ jr nz,.checkSouthMap
+ ld a,[W_MAPCONN1PTR]
+ ld [W_CURMAP],a
+ ld a,[wd378] ; new Y coordinate upon entering north map
+ ld [W_YCOORD],a
+ ld a,[W_XCOORD]
+ ld c,a
+ ld a,[wd379] ; X adjustment upon entering north map
+ add c
+ ld c,a
+ ld [W_XCOORD],a
+ ld a,[wd37a] ; pointer to upper left corner of map without adjustment for X position
+ ld l,a
+ ld a,[wd37b]
+ ld h,a
+ ld b,$00
+ srl c
+ add hl,bc
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+ jp .loadNewMap
+.checkSouthMap
+ ld b,a
+ ld a,[wd524]
+ cp b
+ jr nz,.didNotEnterConnectedMap
+ ld a,[W_MAPCONN2PTR]
+ ld [W_CURMAP],a
+ ld a,[wd383] ; new Y coordinate upon entering south map
+ ld [W_YCOORD],a
+ ld a,[W_XCOORD]
+ ld c,a
+ ld a,[wd384] ; X adjustment upon entering south map
+ add c
+ ld c,a
+ ld [W_XCOORD],a
+ ld a,[wd385] ; pointer to upper left corner of map without adjustment for X position
+ ld l,a
+ ld a,[wd386]
+ ld h,a
+ ld b,$00
+ srl c
+ add hl,bc
+ ld a,l
+ ld [wCurrentTileBlockMapViewPointer],a ; pointer to upper left corner of current tile block map section
+ ld a,h
+ ld [wCurrentTileBlockMapViewPointer + 1],a
+.loadNewMap ; 06ce (0:06ce)
+; load the connected map that was entered
+ ld hl,[wd430]
+ set 4,[hl]
+ ld a,$2
+ ld [wd431],a
+ call LoadMapHeader ; 0dab (0:0dab)
+ call Func_2312 ; music
+ ld b,$09
+ call GoPAL_SET
+; Since the sprite set shouldn't change, this will just update VRAM slots at
+; $C2XE without loading any tile patterns.
+ call InitMapSprites
+ call LoadTileBlockMap
+ jp OverworldLoopLessDelay
+.didNotEnterConnectedMap
+ jp OverworldLoop
+
+; function to play a sound when changing maps
+PlayMapChangeSound:: ; 06ef (0:06ef)
+ ld a,[W_CURMAPTILESET]
+ cp FACILITY
+ jr z,.didNotGoThroughDoor
+ cp CEMETERY
+ jr z,.didNotGoThroughDoor
+ cp UNDERGROUND
+ jr nz,.didNotGoThroughDoor
+ aCoord 8, 8 ; upper left tile of the 4x4 square the player's sprite is standing on
+ cp a,$0b ; door tile in tileset 0
+ jr nz,.didNotGoThroughDoor
+ ld a,(SFX_02_57 - SFX_Headers_02) / 3
+ jr .playSound
+.didNotGoThroughDoor
+ ld a,(SFX_02_5c - SFX_Headers_02) / 3
+.playSound
+ call PlaySound
+ ld a,[wMapPalOffset]
+ and a
+ ret nz
+ jp GBFadeOutToBlack
+
+CheckIfInOutsideMap:: ; 0712 (0:0712)
+; If the player is in an outside map (a town or route), set the z flag
+ ld a, [W_CURMAPTILESET]
+ and a ; most towns/routes have tileset 0 (OVERWORLD)
+ ret z
+ cp PLATEAU ; Route 23 / Indigo Plateau
+ ret
+
+; this function is an extra check that sometimes has to pass in order to warp, beyond just standing on a warp
+; the "sometimes" qualification is necessary because of CheckWarpsNoCollision's behavior
+; depending on the map, either "function 1" or "function 2" is used for the check
+; "function 1" passes when the player is at the edge of the map and is facing towards the outside of the map
+; "function 2" passes when the the tile in front of the player is among a certain set
+; sets carry if the check passes, otherwise clears carry
+ExtraWarpCheck:: ; 071a (0:071a)
+ ld a, [W_CURMAP]
+ cp SS_ANNE_3
+ jr z, .useFunction1
+ cp ROCKET_HIDEOUT_1
+ jr z, .useFunction2
+ cp ROCKET_HIDEOUT_2
+ jr z, .useFunction2
+ cp ROCKET_HIDEOUT_4
+ jr z, .useFunction2
+ cp ROCK_TUNNEL_1
+ jr z, .useFunction2
+ ld a, [W_CURMAPTILESET]
+ and a ; outside tileset (OVERWORLD)
+ jr z, .useFunction2
+ cp SHIP ; S.S. Anne tileset
+ jr z, .useFunction2
+ cp SHIP_PORT ; Vermilion Port tileset
+ jr z, .useFunction2
+ cp PLATEAU ; Indigo Plateau tileset
+ jr z, .useFunction2
+.useFunction1
+ ld hl, IsPlayerFacingEdgeOfMap
+ jr .doBankswitch
+.useFunction2
+ ld hl, IsWarpTileInFrontOfPlayer
+.doBankswitch
+ ld b, BANK(IsWarpTileInFrontOfPlayer)
+ jp Bankswitch
+
+MapEntryAfterBattle:: ; 0750 (0:0750)
+ callba IsPlayerStandingOnWarp ; for enabling warp testing after collisions
+ ld a,[wMapPalOffset]
+ and a
+ jp z,GBFadeInFromWhite
+ jp LoadGBPal
+
+HandleBlackOut:: ; 0762 (0:0762)
+; For when all the player's pokemon faint.
+; Does not print the "blacked out" message.
+
+ call GBFadeOutToBlack
+ ld a, $08
+ call StopMusic
+ ld hl, wd72e
+ res 5, [hl]
+ callsb ResetStatusAndHalveMoneyOnBlackout ; also Bank(SpecialWarpIn) and Bank(SpecialEnterMap)
+ callab Func_f0274 ; 3c:4274
+ call SpecialWarpIn
+ call Func_2312
+ jp SpecialEnterMap
+
+StopMusic:: ; 0788 (0:0788)
+ ld [wMusicHeaderPointer], a
+ call StopAllMusic
+.wait
+ ld a, [wMusicHeaderPointer]
+ and a
+ jr nz, .wait
+ jp StopAllSounds
+
+HandleFlyWarpOrDungeonWarp:: ; 0794 (0:0794)
+ call UpdateSprites
+ call Delay3
+ xor a
+ ld [wBattleResult], a
+ ld [wWalkBikeSurfState], a
+ ld [W_ISINBATTLE], a
+ ld [wMapPalOffset], a
+ ld hl, wd732
+ set 2, [hl] ; fly warp or dungeon warp
+ res 5, [hl] ; forced to ride bike
+ call LeaveMapAnim
+ call LoadPlayerSpriteGraphics
+ callsb SpecialWarpIn
+ jp SpecialEnterMap
+
+LeaveMapAnim:: ; 07bc (0:07bc)
+ ld b, BANK(_LeaveMapAnim)
+ ld hl, _LeaveMapAnim
+ jp Bankswitch
+
+Func_07c4:: ; 07c4 (0:07c4)
+ ld a, [wWalkBikeSurfState]
+ and a
+ ret z
+ xor a
+ ld [wWalkBikeSurfState],a
+ ld hl,wd732
+ bit 4,[hl]
+ ret z
+ call PlayDefaultMusic
+ ret
+
+LoadPlayerSpriteGraphics:: ; 07d7 (0:07d7)
+; Load sprite graphics based on whether the player is standing, biking, or surfing.
+
+ ; 0: standing
+ ; 1: biking
+ ; 2: surfing
+
+ ld a, [wWalkBikeSurfState]
+ dec a
+ jr z, .ridingBike
+
+ ld a, [hTilesetType]
+ and a
+ jr nz, .determineGraphics
+ jr .startWalking
+
+.ridingBike
+ ; If the bike can't be used,
+ ; start walking instead.
+ call IsBikeRidingAllowed
+ jr c, .determineGraphics
+
+.startWalking
+ xor a
+ ld [wWalkBikeSurfState], a
+ ld [wWalkBikeSurfStateCopy], a
+ jp LoadWalkingPlayerSpriteGraphics
+
+.determineGraphics
+ ld a, [wWalkBikeSurfState]
+ and a
+ jp z, LoadWalkingPlayerSpriteGraphics
+ dec a
+ jp z, LoadBikePlayerSpriteGraphics
+ dec a
+ jp z, LoadSurfingPlayerSpriteGraphics
+ jp LoadWalkingPlayerSpriteGraphics
+
+IsBikeRidingAllowed:: ; 0805 (0:0805)
+; The bike can be used on Route 23 and Indigo Plateau,
+; or maps with tilesets in BikeRidingTilesets.
+; Return carry if biking is allowed.
+
+ ld a, [W_CURMAP]
+ cp ROUTE_23
+ jr z, .allowed
+ cp INDIGO_PLATEAU
+ jr z, .allowed
+
+ ld a, [W_CURMAPTILESET]
+ ld b, a
+ ld hl, BikeRidingTilesets
+.loop
+ ld a, [hli]
+ cp b
+ jr z, .allowed
+ inc a
+ jr nz, .loop
+ and a
+ ret
+
+.allowed
+ scf
+ ret
+
+INCLUDE "data/bike_riding_tilesets.asm"
+
+; load the tile pattern data of the current tileset into VRAM
+LoadTilesetTilePatternData:: ; 0828 (0:0828)
+ ld a,[W_TILESETGFXPTR]
+ ld l,a
+ ld a,[W_TILESETGFXPTR + 1]
+ ld h,a
+ ld de,vTileset
+ ld bc,$600
+ ld a,[W_TILESETBANK]
+ jp FarCopyData2
+
+; this loads the current maps complete tile map (which references blocks, not individual tiles) to C6E8
+; it can also load partial tile maps of connected maps into a border of length 3 around the current map
+LoadTileBlockMap:: ; 083c (0:083c)
+; fill C6E8-CBFB with the background tile
+ ld hl,wOverworldMap
+ ld bc,$0514
+ ld a,[wd3ad] ; background tile number
+ call FillMemory
+; load tile map of current map (made of tile block IDs)
+; a 3-byte border at the edges of the map is kept so that there is space for map connections
+ ld hl,wOverworldMap
+ ld a,[W_CURMAPWIDTH]
+ ld [$ff8c],a
+ add a,$06 ; border (east and west)
+ ld [$ff8b],a ; map width + border
+ ld b,$00
+ ld c,a
+; make space for north border (next 3 lines)
+ add hl,bc
+ add hl,bc
+ add hl,bc
+ ld c,$03
+ add hl,bc ; this puts us past the (west) border
+ ld a,[W_MAPDATAPTR] ; tile map pointer
+ ld e,a
+ ld a,[W_MAPDATAPTR + 1]
+ ld d,a ; de = tile map pointer
+ ld a,[W_CURMAPHEIGHT]
+ ld b,a
+.rowLoop ; copy one row each iteration
+ push hl
+ ld a,[$ff8c] ; map width (without border)
+ ld c,a
+.rowInnerLoop
+ ld a,[de]
+ inc de
+ ld [hli],a
+ dec c
+ jr nz,.rowInnerLoop
+; add the map width plus the border to the base address of the current row to get the next row's address
+ pop hl
+ ld a,[$ff8b] ; map width + border
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ dec b
+ jr nz,.rowLoop
+.northConnection
+ ld a,[W_MAPCONN1PTR]
+ cp a,$ff
+ jr z,.southConnection
+ call SwitchToMapRomBank
+ ld a,[wd372]
+ ld l,a
+ ld a,[wd373]
+ ld h,a
+ ld a,[wd374]
+ ld e,a
+ ld a,[wd375]
+ ld d,a
+ ld a,[wd376]
+ ld [$ff8b],a
+ ld a,[wd377]
+ ld [$ff8c],a
+ call LoadNorthSouthConnectionsTileMap
+.southConnection
+ ld a,[W_MAPCONN2PTR]
+ cp a,$ff
+ jr z,.westConnection
+ call SwitchToMapRomBank
+ ld a,[wd37d]
+ ld l,a
+ ld a,[wd37e]
+ ld h,a
+ ld a,[wd37f]
+ ld e,a
+ ld a,[wd380]
+ ld d,a
+ ld a,[wd381]
+ ld [$ff8b],a
+ ld a,[wd382]
+ ld [$ff8c],a
+ call LoadNorthSouthConnectionsTileMap
+.westConnection
+ ld a,[W_MAPCONN3PTR]
+ cp a,$ff
+ jr z,.eastConnection
+ call SwitchToMapRomBank
+ ld a,[wd388]
+ ld l,a
+ ld a,[wd389]
+ ld h,a
+ ld a,[wd38a]
+ ld e,a
+ ld a,[wd38b]
+ ld d,a
+ ld a,[wd38c]
+ ld b,a
+ ld a,[wd38d]
+ ld [$ff8b],a
+ call LoadEastWestConnectionsTileMap
+.eastConnection
+ ld a,[W_MAPCONN4PTR]
+ cp a,$ff
+ jr z,.done
+ call SwitchToMapRomBank
+ ld a,[wd393]
+ ld l,a
+ ld a,[wd394]
+ ld h,a
+ ld a,[wd395]
+ ld e,a
+ ld a,[wd396]
+ ld d,a
+ ld a,[wd397]
+ ld b,a
+ ld a,[wd398]
+ ld [$ff8b],a
+ call LoadEastWestConnectionsTileMap
+.done
+ ret
+
+LoadNorthSouthConnectionsTileMap:: ; 0919 (0:0919)
+ ld c,$03
+.loop
+ push de
+ push hl
+ ld a,[$ff8b] ; width of connection
+ ld b,a
+.innerLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec b
+ jr nz,.innerLoop
+ pop hl
+ pop de
+ ld a,[$ff8c] ; width of connected map
+ add l
+ ld l,a
+ jr nc,.noCarry1
+ inc h
+.noCarry1
+ ld a,[W_CURMAPWIDTH]
+ add a,$06
+ add e
+ ld e,a
+ jr nc,.noCarry2
+ inc d
+.noCarry2
+ dec c
+ jr nz,.loop
+ ret
+
+LoadEastWestConnectionsTileMap:: ; 093d (0:093d)
+ push hl
+ push de
+ ld c,$03
+.innerLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.innerLoop
+ pop de
+ pop hl
+ ld a,[$ff8b] ; width of connected map
+ add l
+ ld l,a
+ jr nc,.noCarry1
+ inc h
+.noCarry1
+ ld a,[W_CURMAPWIDTH]
+ add a,$06
+ add e
+ ld e,a
+ jr nc,.noCarry2
+ inc d
+.noCarry2
+ dec b
+ jr nz,LoadEastWestConnectionsTileMap
+ ret
+
+; function to check if there is a sign or sprite in front of the player
+; if so, carry is set. otherwise, carry is cleared
+IsSpriteOrSignInFrontOfPlayer:: ; 095e (0:095e)
+ xor a
+ ld [hSpriteIndexOrTextID],a
+ ld a,[wd4b0] ; number of signs in the map
+ and a
+ jr z,.extendRangeOverCounter
+; if there are signs
+ predef GetTileAndCoordsInFrontOfPlayer ; get the coordinates in front of the player in de
+ call SignLoop
+ ret c
+.extendRangeOverCounter
+; check if the player is front of a counter in a pokemon center, pokemart, etc. and if so, extend the range at which he can talk to the NPC
+ predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player in c
+ ld hl,W_TILESETTALKINGOVERTILES ; list of tiles that extend talking range (counter tiles)
+ ld b,$03
+ ld d,$20 ; talking range in pixels (long range)
+.counterTilesLoop
+ ld a,[hli]
+ cp c
+ jr z,IsSpriteInFrontOfPlayer2 ; jumps if the tile in front of the player is a counter tile
+ dec b
+ jr nz,.counterTilesLoop
+
+; sets carry flag if a sprite is in front of the player, resets if not
+IsSpriteInFrontOfPlayer:: ; 0983 (0:0983)
+ ld d,$10 ; talking range in pixels (normal range)
+IsSpriteInFrontOfPlayer2:: ; 0985 (0:0985)
+ ld bc,$3c40 ; Y and X position of player sprite
+ ld a,[wSpriteStateData1 + 9] ; direction the player is facing
+.checkIfPlayerFacingUp
+ cp a,$04
+ jr nz,.checkIfPlayerFacingDown
+; facing up
+ ld a,b
+ sub d
+ ld b,a
+ ld a,$08
+ jr .doneCheckingDirection
+.checkIfPlayerFacingDown
+ cp a,$00
+ jr nz,.checkIfPlayerFacingRight
+; facing down
+ ld a,b
+ add d
+ ld b,a
+ ld a,$04
+ jr .doneCheckingDirection
+.checkIfPlayerFacingRight
+ cp a,$0c
+ jr nz,.playerFacingLeft
+; facing right
+ ld a,c
+ add d
+ ld c,a
+ ld a,$01
+ jr .doneCheckingDirection
+.playerFacingLeft
+; facing left
+ ld a,c
+ sub d
+ ld c,a
+ ld a,$02
+.doneCheckingDirection
+ ld [wd52a],a
+ ld hl,wSpriteStateData1 + $10
+; yellow does not have the "if sprites are existant" check
+ ld e,$01
+ ld d,$f
+.spriteLoop
+ push hl
+ ld a,[hli] ; image (0 if no sprite)
+ and a
+ jr z,.nextSprite
+ inc l
+ ld a,[hli] ; sprite visibility
+ inc a
+ jr z,.nextSprite
+ inc l
+ ld a,[hli] ; Y location
+ cp b
+ jr nz,.nextSprite
+ inc l
+ ld a,[hl] ; X location
+ cp c
+ jr z,.foundSpriteInFrontOfPlayer
+.nextSprite
+ pop hl
+ ld a,l
+ add a,$10
+ ld l,a
+ inc e
+ dec d
+ jr nz,.spriteLoop
+ xor a
+ ret
+.foundSpriteInFrontOfPlayer
+ pop hl
+ ld a,l
+ and a,$f0
+ inc a
+ ld l,a
+ set 7,[hl]
+ ld a,e
+ ld [hSpriteIndexOrTextID],a
+ ld a,[hSpriteIndexOrTextID] ; possible useless read because a already has the value of the read address
+ cp a,$f
+ jr nz,.dontwritetowd436
+ ld a,$FF
+ ld [wd436],a
+.dontwritetowd436
+ scf
+ ret
+
+SignLoop:: ; 09f2 (0:09f2)
+; search if a player is facing a sign
+ ld hl,wd4b1 ; start of sign coordinates
+ ld a,[wd4b0] ; number of signs in the map
+ ld b,a
+ ld c,$00
+.signLoop
+ inc c
+ ld a,[hli] ; sign Y
+ cp d
+ jr z,.yCoordMatched
+ inc hl
+ jr .retry
+.yCoordMatched
+ ld a,[hli] ; sign X
+ cp e
+ jr nz,.retry
+.xCoordMatched
+; found sign
+ push hl
+ push bc
+ ld hl,wd4d1 ; start of sign text ID's
+ ld b,$00
+ dec c
+ add hl,bc
+ ld a,[hl]
+ ld [hSpriteIndexOrTextID],a ; store sign text ID
+ pop bc
+ pop hl
+ scf
+ ret
+.retry
+ dec b
+ jr nz,.signLoop
+ xor a
+ ret
+
+; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing)
+; sets the carry flag if there is a collision, and unsets it if there isn't a collision
+CollisionCheckOnLand:: ; 0a1c (0:0a1c)
+ ld a,[wd736]
+ bit 6,a ; is the player jumping?
+ jr nz,.noCollision
+; if not jumping a ledge
+ ld a,[wSimulatedJoypadStatesIndex]
+ and a
+ jr nz,.noCollision ; no collisions when the player's movements are being controlled by the game
+ ld a,[wd52a] ; the direction that the player is trying to go in
+ ld d,a
+ ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code)
+ and d ; check if a sprite is in the direction the player is trying to go
+ nop ; ??? why is this in the code
+ jr nz,.collision
+ xor a
+ ld [hSpriteIndexOrTextID],a
+ call IsSpriteInFrontOfPlayer ; check for sprite collisions again? when does the above check fail to detect a sprite collision?
+ jr nc,.asm_0a5c
+ res 7,[hl]
+ ld a,[hSpriteIndexOrTextID]
+ and a ; was there a sprite collision?
+ jr z,.asm_0a5c
+; if no sprite collision
+ cp $f
+ jr nz,.collision
+ call CheckForJumpingAndTilePairCollisions
+ jr nz,.collision
+ ld a,[hJoyHeld]
+ and $2
+ jr nz,.asm_0a5c
+ ld hl,wd435
+ ld a,[hl]
+ and a
+ jr z,.asm_0a5c
+ dec [hl]
+ jr nz,.collision
+.asm_0a5c
+ ld hl,TilePairCollisionsLand
+ call CheckForJumpingAndTilePairCollisions
+ jr c,.collision
+ call CheckTilePassable
+ jr nc,.noCollision
+.collision
+ ld a,[wc02a]
+ cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing
+ jr z,.setCarry
+ ld a,(SFX_02_5b - SFX_Headers_02) / 3
+ call PlaySound ; play collision sound (if it's not already playing)
+.setCarry
+ scf
+ ret
+.noCollision
+ and a
+ ret
+
+; function that checks if the tile in front of the player is passable
+; clears carry if it is, sets carry if not
+CheckTilePassable:: ; 0a79 (0:0a79)
+ predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player
+ ld a,[wTileInFrontOfPlayer] ; tile in front of player
+ ld c,a
+ call IsTilePassable
+ ret
+
+; check if the player is going to jump down a small ledge
+; and check for collisions that only occur between certain pairs of tiles
+; Input: hl - address of directional collision data
+; sets carry if there is a collision and unsets carry if not
+CheckForJumpingAndTilePairCollisions:: ; 0a86 (0:0a86)
+ push hl
+ predef GetTileAndCoordsInFrontOfPlayer ; get the tile in front of the player
+ push de
+ push bc
+ callba HandleLedges ; check if the player is trying to jump a ledge
+ pop bc
+ pop de
+ pop hl
+ and a
+ ld a,[wd736]
+ bit 6,a ; is the player jumping?
+ ret nz
+; if not jumping
+
+CheckForTilePairCollisions2:: ; 0aa0 (0:0aa0)
+ aCoord 8, 9 ; tile the player is on
+ ld [wcf0e],a
+
+CheckForTilePairCollisions:: ; 0aa6 (0:0aa6)
+ ld a,[wTileInFrontOfPlayer]
+ ld c,a
+.tilePairCollisionLoop
+ ld a,[W_CURMAPTILESET] ; tileset number
+ ld b,a
+ ld a,[hli]
+ cp a,$ff
+ jr z,.noMatch
+ cp b
+ jr z,.tilesetMatches
+ inc hl
+.retry
+ inc hl
+ jr .tilePairCollisionLoop
+.tilesetMatches
+ ld a,[wcf0e] ; tile the player is on
+ ld b,a
+ ld a,[hl]
+ cp b
+ jr z,.currentTileMatchesFirstInPair
+ inc hl
+ ld a,[hl]
+ cp b
+ jr z,.currentTileMatchesSecondInPair
+ jr .retry
+.currentTileMatchesFirstInPair
+ inc hl
+ ld a,[hl]
+ cp c
+ jr z,.foundMatch
+ jr .tilePairCollisionLoop
+.currentTileMatchesSecondInPair
+ dec hl
+ ld a,[hli]
+ cp c
+ inc hl
+ jr nz,.tilePairCollisionLoop
+.foundMatch
+ scf
+ ret
+.noMatch
+ and a
+ ret
+
+; FORMAT: tileset number, tile 1, tile 2
+; terminated by 0xFF
+; these entries indicate that the player may not cross between tile 1 and tile 2
+; it's mainly used to simulate differences in elevation
+
+TilePairCollisionsLand:: ; 0ada (0:0ada)
+ db CAVERN, $20, $05
+ db CAVERN, $41, $05
+ db FOREST, $30, $2E
+ db CAVERN, $2A, $05
+ db CAVERN, $05, $21
+ db FOREST, $52, $2E
+ db FOREST, $55, $2E
+ db FOREST, $56, $2E
+ db FOREST, $20, $2E
+ db FOREST, $5E, $2E
+ db FOREST, $5F, $2E
+ db $FF
+
+TilePairCollisionsWater:: ; 0afc (0:0afc)
+ db FOREST, $14, $2E
+ db FOREST, $48, $2E
+ db CAVERN, $14, $05
+ db $FF
+
+; this builds a tile map from the tile block map based on the current X/Y coordinates of the player's character
+LoadCurrentMapView:: ; 0b06 (0:0b06)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,[W_TILESETBANK] ; tile data ROM bank
+ call BankswitchCommon ; switch to ROM bank that contains tile data
+ ld a,[wCurrentTileBlockMapViewPointer] ; address of upper left corner of current map view
+ ld e,a
+ ld a,[wCurrentTileBlockMapViewPointer + 1]
+ ld d,a
+ ld hl,wTileMapBackup
+ ld b,$05
+.rowLoop ; each loop iteration fills in one row of tile blocks
+ push hl
+ push de
+ ld c,$06
+.rowInnerLoop ; loop to draw each tile block of the current row
+ push bc
+ push de
+ push hl
+ ld a,[de]
+ ld c,a ; tile block number
+ call DrawTileBlock
+ pop hl
+ pop de
+ pop bc
+ inc hl
+ inc hl
+ inc hl
+ inc hl
+ inc de
+ dec c
+ jr nz,.rowInnerLoop
+; update tile block map pointer to next row's address
+ pop de
+ ld a,[W_CURMAPWIDTH]
+ add a,$06
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry
+; update tile map pointer to next row's address
+ pop hl
+ ld a,$60
+ add l
+ ld l,a
+ jr nc,.noCarry2
+ inc h
+.noCarry2
+ dec b
+ jr nz,.rowLoop
+ ld hl,wTileMapBackup
+ ld bc,$0000
+.adjustForYCoordWithinTileBlock
+ ld a,[W_YBLOCKCOORD]
+ and a
+ jr z,.adjustForXCoordWithinTileBlock
+ ld bc,$0030
+ add hl,bc
+.adjustForXCoordWithinTileBlock
+ ld a,[W_XBLOCKCOORD]
+ and a
+ jr z,.copyToVisibleAreaBuffer
+ ld bc,$0002
+ add hl,bc
+.copyToVisibleAreaBuffer
+ ld de,wTileMap ; base address for the tiles that are directly transfered to VRAM during V-blank
+ ld b,$12
+.rowLoop2
+ ld c,$14
+.rowInnerLoop2
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.rowInnerLoop2
+ ld a,$04
+ add l
+ ld l,a
+ jr nc,.noCarry3
+ inc h
+.noCarry3
+ dec b
+ jr nz,.rowLoop2
+ pop af
+ call BankswitchCommon ; restore previous ROM bank
+ ret
+
+AdvancePlayerSprite:: ; 0b7f (0:0b7f)
+ ld a,[wUpdateSpritesEnabled]
+ push af
+ ld a,$FF
+ ld [wUpdateSpritesEnabled],a
+ ld hl, _AdvancePlayerSorite ; 3c:410c
+ ld b, BANK(_AdvancePlayerSprite)
+ call Bankswitch
+ pop af
+ ld [wUpdateSpritesEnabled],a
+ ret
+
+; the following 6 functions are used to tell the V-blank handler to redraw
+; the portion of the map that was newly exposed due to the player's movement
+
+ScheduleNorthRowRedraw:: ; 0b95 (0:0b95)
+ hlCoord 0, 0
+ call CopyToScreenEdgeTiles
+ ld a,[wMapViewVRAMPointer]
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,REDRAWROW
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+CopyToScreenEdgeTiles:: ; 0baa (0:0baa)
+ ld de,wScreenEdgeTiles
+ ld c,2 * 20
+.loop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.loop
+ ret
+
+ScheduleSouthRowRedraw:: ; 0bb6 (0:0bb6)
+ hlCoord 0, 16
+ call CopyToScreenEdgeTiles
+ ld a,[wMapViewVRAMPointer]
+ ld l,a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld h,a
+ ld bc,$0200
+ add hl,bc
+ ld a,h
+ and a,$03
+ or a,$98
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,l
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,REDRAWROW
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+ScheduleEastColumnRedraw:: ; 0bd6 (0:0bd7)
+ hlCoord 18, 0
+ call ScheduleColumnRedrawHelper
+ ld a,[wMapViewVRAMPointer]
+ ld c,a
+ and a,$e0
+ ld b,a
+ ld a,c
+ add a,18
+ and a,$1f
+ or b
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,REDRAWCOL
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+ScheduleColumnRedrawHelper:: ; 0bf6 (0:0bf6)
+ ld de,wScreenEdgeTiles
+ ld c,$12
+.loop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ ld a,[hl]
+ ld [de],a
+ inc de
+ ld a,19
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ dec c
+ jr nz,.loop
+ ret
+
+ScheduleWestColumnRedraw:: ; 0c0c (0:0c0c)
+ hlCoord 0, 0
+ call ScheduleColumnRedrawHelper
+ ld a,[wMapViewVRAMPointer]
+ ld [H_SCREENEDGEREDRAWADDR],a
+ ld a,[wMapViewVRAMPointer + 1]
+ ld [H_SCREENEDGEREDRAWADDR + 1],a
+ ld a,REDRAWCOL
+ ld [H_SCREENEDGEREDRAW],a
+ ret
+
+; function to write the tiles that make up a tile block to memory
+; Input: c = tile block ID, hl = destination address
+DrawTileBlock:: ; 0c21 (0:0c21)
+ push hl
+ ld a,[W_TILESETBLOCKSPTR] ; pointer to tiles
+ ld l,a
+ ld a,[W_TILESETBLOCKSPTR + 1]
+ ld h,a
+ ld a,c
+ swap a
+ ld b,a
+ and a,$f0
+ ld c,a
+ ld a,b
+ and a,$0f
+ ld b,a ; bc = tile block ID * 0x10
+ add hl,bc
+ ld d,h
+ ld e,l ; de = address of the tile block's tiles
+ pop hl
+ ld c,$04 ; 4 loop iterations
+.loop ; each loop iteration, write 4 tile numbers
+ push bc
+ ld a,[de]
+ ld [hli],a
+ inc de
+ ld a,[de]
+ ld [hli],a
+ inc de
+ ld a,[de]
+ ld [hli],a
+ inc de
+ ld a,[de]
+ ld [hl],a
+ inc de
+ ld bc,$0015
+ add hl,bc
+ pop bc
+ dec c
+ jr nz,.loop
+ ret
+
+; function to update joypad state and simulate button presses
+JoypadOverworld:: ; 0c51 (0:0c51)
+ xor a
+ ld [wSpriteStateData1 + 3],a
+ ld [wSpriteStateData1 + 5],a
+ call RunMapScript
+ call Joypad
+ call ForceBikeDown
+ call AreInputsSimulated
+ ret
+
+ForceBikeDown:: ; 0c65 (0:0c65)
+ ld a,[W_FLAGS_D733]
+ bit 3,a ; check if a trainer wants a challenge
+ ret nz
+ ld a,[W_CURMAP]
+ cp a,ROUTE_17 ; Cycling Road
+ ret nz
+ ld a,[hJoyHeld]
+ and a,D_DOWN | D_UP | D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON
+ jr nz,.notForcedDownwards
+ ld a,D_DOWN
+ ld [hJoyHeld],a ; on the cycling road, if there isn't a trainer and the player isn't pressing buttons, simulate a down press
+ ret
+
+AreInputsSimulated:: ; 0c7b (0:0c7b)
+ ld a,[wd730]
+ bit 7,a
+ ret z
+; if simulating button presses
+ ld a,[hJoyHeld]
+ ld b,a
+ ld a,[wOverrideSimulatedJoypadStatesMask] ; bit mask for button presses that override simulated ones
+ and b
+ ret nz ; return if the simulated button presses are overridden
+ call GetSimulatedInput
+ jr nc,.doneSimulating
+ ld [hJoyHeld],a ; store simulated button press in joypad state
+ and a
+ ret nz
+ ld [hJoyPressed],a
+ ld [hJoyReleased],a
+ ret
+
+; if done simulating button presses
+.doneSimulating
+ xor a
+ ld [wWastedByteCD3A],a
+ ld [wSimulatedJoypadStatesIndex],a
+ ld [wSimulatedJoypadStatesEnd],a
+ ld [wJoyIgnore],a
+ ld [hJoyHeld],a
+ ld hl,wd736
+ ld a,[hl]
+ and a,$f8
+ ld [hl],a
+ ld hl,wd730
+ res 7,[hl]
+ ret
+
+GetSimulatedInput:: ; 0cb3 (0:0cb3)
+ ld hl,wSimulatedJoypadStatesIndex
+ dec [hl]
+ ld a,[hl]
+ cp a,$ff
+ jr z,.endofsimulatedinputs ; if the end of the simulated button presses has been reached
+ push de
+ ld e,a
+ ld d,$0
+ ld hl,wSimulatedJoypadStatesEnd
+ add hl,de
+ ld a,[hl]
+ pop de
+ scf
+ ret
+.endofsimulatedinputs
+ and a
+ ret
+
+
+; function to check the tile ahead to determine if the character should get on land or keep surfing
+; sets carry if there is a collision and clears carry otherwise
+; It seems that this function has a bug in it, but due to luck, it doesn't
+; show up. After detecting a sprite collision, it jumps to the code that
+; checks if the next tile is passable instead of just directly jumping to the
+; "collision detected" code. However, it doesn't store the next tile in c,
+; so the old value of c is used. 2429 is always called before this function,
+; and 2429 always sets c to 0xF0. There is no 0xF0 background tile, so it
+; is considered impassable and it is detected as a collision.
+CollisionCheckOnWater:: ; 0cca (0:0cca)
+ ld a,[wd730]
+ bit 7,a
+ jp nz,.noCollision ; return and clear carry if button presses are being simulated
+ ld a,[wd52a] ; the direction that the player is trying to go in
+ ld d,a
+ ld a,[wSpriteStateData1 + 12] ; the player sprite's collision data (bit field) (set in the sprite movement code)
+ and d ; check if a sprite is in the direction the player is trying to go
+ jr nz,.checkIfNextTileIsPassable ; bug?
+ ld hl,TilePairCollisionsWater
+ call CheckForJumpingAndTilePairCollisions
+ jr c,.collision
+ predef GetTileAndCoordsInFrontOfPlayer ; get tile in front of player (puts it in c and [wTileInFrontOfPlayer])
+ callab IsNextTileShoreOrWater ; 3:6808
+ jr c,.noCollsion
+ ld a,[wTileInFrontOfPlayer] ; tile in front of player
+ ld c,a
+ call IsTilePassable
+ jr nc,.stopSurfing
+.collision
+ ld a,[wc02a]
+ cp a,(SFX_02_5b - SFX_Headers_02) / 3 ; check if collision sound is already playing
+ jr z,.setCarry
+ ld a,(SFX_02_5b - SFX_Headers_02) / 3
+ call PlaySound ; play collision sound (if it's not already playing)
+.setCarry
+ scf
+ jr .done
+.checkIfVermilionDockTileset
+ ld a, [W_CURMAPTILESET] ; tileset
+ cp SHIP_PORT ; Vermilion Dock tileset
+ jr nz, .noCollision ; keep surfing if it's not the boarding platform tile
+ jr .stopSurfing ; if it is the boarding platform tile, stop surfing
+.stopSurfing ; based game freak
+ ld a,$3
+ ld [wd431],a
+ ld hl,wd430
+ set 5,[hl]
+ xor a
+ ld [wWalkBikeSurfState],a
+ call LoadPlayerSpriteGraphics
+ call PlayDefaultMusic
+ jr .noCollision
+.noCollision ; ...and they do the same mistake twice
+ and a
+.done
+ ret
+
+; function to run the current map's script
+RunMapScript:: ; 0d2c (0:0d2c)
+ push hl
+ push de
+ push bc
+ callba TryPushingBoulder
+ ld a,[wFlags_0xcd60]
+ bit 1,a ; play boulder dust animation
+ jr z,.afterBoulderEffect
+ callba DoBoulderDustAnimation
+.afterBoulderEffect
+ pop bc
+ pop de
+ pop hl
+ call RunNPCMovementScript
+ ld a,[W_CURMAP] ; current map number
+ call SwitchToMapRomBank ; change to the ROM bank the map's data is in
+ ld hl,W_MAPSCRIPTPTR
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ ld de,.return
+ push de
+ jp [hl] ; jump to script
+.return
+ ret
+
+Func_0d5e:: ; 0d5e (0:0d5e)
+; new sprite copy stuff
+ xor a
+ ld [wd473],a
+ ld b,BANK(RedSprite)
+ ld de,RedSprite ; $4180
+ jr LoadPlayerSpriteGraphicsCommon
+
+Func_0d69:: ; 0d69 (0:0d69)
+ ld a,[wd473]
+ and a
+ jr z,.asm_0d75
+ dec a
+ jr z,.asm_0d83
+ dec a
+ jr z,.asm_0d7c
+.asm_0d75
+ ld a,[wd472]
+ bit 6,a
+ jr z,LoadSurfingPlayerSpriteGraphics
+.asm_0d7c
+ ld b,BANK(Pointer_fedef)
+ ld de,Pointer_fedef ; 3f:6def
+ jr LoadPlayerSpriteGraphicsCommon
+
+LoadSurfingPlayerSpriteGraphics:: ; 0d83 (0:0d83)
+ ld b,BANK(RedSprite) ; not sure, but probably same bank (5)
+ ld de,SeelSprite
+ jr LoadPlayerSpriteGraphicsCommon
+
+LoadBikePlayerSpriteGraphics:: ; 0d8a (0:0d8a)
+ ld de,RedCyclingSprite
+LoadPlayerSpriteGraphicsCommon:: ; 0d8f (0:0d8f)
+ ld hl,vNPCSprites
+ push de
+ push hl
+ ld c, $c
+ call CopyVideoData
+ pop hl
+ pop de
+ ld a,$c0
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry
+ set 3,h
+ ld c,$c
+ jp CopyVideoData
+
+; function to load data from the map header
+LoadMapHeader:: ; 0dab (0:0dab)
+ callba MarkTownVisitedAndLoadMissableObjects
+ jr .asm_0dbd
+ callba Func_f0a55 ; 3c:4a55
+.asm_0dbd
+ ld a,[W_CURMAPTILESET]
+ ld [wd119],a
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ ld a,[W_CURMAPTILESET]
+ ld b,a
+ res 7,a
+ ld [W_CURMAPTILESET],a
+ ld [$ff8b],a
+ bit 7,b
+ ret nz
+ call GetMapHeaderPointer
+; copy the first 10 bytes (the fixed area) of the map data to D367-D370
+ ld de,W_CURMAPTILESET
+ ld c,$0a
+.copyFixedHeaderLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.copyFixedHeaderLoop
+; initialize all the connected maps to disabled at first, before loading the actual values
+ ld a,$ff
+ ld [W_MAPCONN1PTR],a
+ ld [W_MAPCONN2PTR],a
+ ld [W_MAPCONN3PTR],a
+ ld [W_MAPCONN4PTR],a
+; copy connection data (if any) to WRAM
+ ld a,[W_MAPCONNECTIONS]
+ ld b,a
+.checkNorth
+ bit 3,b
+ jr z,.checkSouth
+ ld de,W_MAPCONN1PTR
+ call CopyMapConnectionHeader
+.checkSouth
+ bit 2,b
+ jr z,.checkWest
+ ld de,W_MAPCONN2PTR
+ call CopyMapConnectionHeader
+.checkWest
+ bit 1,b
+ jr z,.checkEast
+ ld de,W_MAPCONN3PTR
+ call CopyMapConnectionHeader
+.checkEast
+ bit 0,b
+ jr z,.getObjectDataPointer
+ ld de,W_MAPCONN4PTR
+ call CopyMapConnectionHeader
+.getObjectDataPointer
+ ld a,[hli]
+ ld [wd3a9],a
+ ld a,[hli]
+ ld [wd3aa],a
+ push hl
+ ld a,[wd3a9]
+ ld l,a
+ ld a,[wd3aa]
+ ld h,a ; hl = base of object data
+ ld de,wd3ad ; background tile ID
+ ld a,[hli]
+ ld [de],a ; save background tile ID
+.loadWarpData
+ ld a,[hli]
+ ld [wNumberOfWarps],a
+ and a
+ jr z,.loadSignData
+ ld c,a
+ ld de,wWarpEntries
+.warpLoop ; one warp per loop iteration
+ ld b,$04
+.warpInnerLoop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec b
+ jr nz,.warpInnerLoop
+ dec c
+ jr nz,.warpLoop
+.loadSignData
+ ld a,[hli] ; number of signs
+ ld [wd4b0],a ; save the number of signs
+ and a ; are there any signs?
+ jr z,.loadSpriteData ; if not, skip this
+ call CopySignData ; 0eb3 (0:0eb3)
+.loadSpriteData
+ ld a,[wd72e]
+ bit 5,a ; did a battle happen immediately before this?
+ jp nz,.finishUp ; if so, skip this because battles don't destroy this data
+ call InitSprites
+.finishUp
+ predef LoadTilesetHeader
+ ld a,[wd72e]
+ bit 5,a ; did a battle happen immediately before this?
+ jr nz,.asm_0e73
+ callab Func_fc4fa ; 3f:44fa
+ callab LoadWildData
+ pop hl ; restore hl from before going to the warp/sign/sprite data (this value was saved for seemingly no purpose)
+ ld a,[W_CURMAPHEIGHT] ; map height in 4x4 tile blocks
+ add a ; double it
+ ld [wd524],a ; store map height in 2x2 tile blocks
+ ld a,[W_CURMAPWIDTH] ; map width in 4x4 tile blocks
+ add a ; double it
+ ld [wd525],a ; map width in 2x2 tile blocks
+ ld a,[W_CURMAP]
+ ld c,a
+ ld b,$00
+ ld a,[H_LOADEDROMBANK]
+ push af
+ switchbank MapSongBanks
+ ld hl, MapSongBanks ; 3f:4000
+ add hl,bc
+ add hl,bc
+ ld a,[hli]
+ ld [wd35b],a ; music 1
+ ld a,[hl]
+ ld [wd35c],a ; music 2
+ pop af
+ call BankswitchCommon
+ ret
+
+; function to copy map connection data from ROM to WRAM
+; Input: hl = source, de = destination
+CopyMapConnectionHeader:: ; 1238 (0:1238)
+ ld c,$0b
+.loop
+ ld a,[hli]
+ ld [de],a
+ inc de
+ dec c
+ jr nz,.loop
+ ret
+
+CopySignData:: ; 0eb3 (0:0eb3)
+ ld de,wd4b1 ; start of sign coords
+ ld bc,wd4d1 ; start of sign text ids
+ ld a,[wd4b0] ; number of signs
+.signcopyloop
+ push af
+ ld a,[hli]
+ ld [de],a ; copy y coord
+ inc de
+ ld a,[hli]
+ ld [de],a ; copy x coord
+ inc de
+ ld a,[hli]
+ ld [bc],a ; copy sign text id
+ inc bc
+ pop af
+ dec a
+ jr nz,.signcopyloop
+ ret
+
+; function to load map data
+LoadMapData:: ; 1241 (0:1241)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ call DisableLCD
+ call ResetMapVariables
+ call LoadTextBoxTilePatterns
+ call LoadMapHeader
+ call InitMapSprites ; load tile pattern data for sprites
+ call LoadScreenRelatedData
+ call CopyMapViewToVRAM
+ ld a,$01
+ ld [wUpdateSpritesEnabled],a
+ call EnableLCD
+ ld b,$09
+ call GoPAL_SET
+ call LoadPlayerSpriteGraphics
+ ld a,[wd732]
+ and a,1 << 4 | 1 << 3 ; fly warp or dungeon warp
+ jr nz,.restoreRomBank
+ ld a,[W_FLAGS_D733]
+ bit 1,a
+ jr nz,.restoreRomBank
+ call Func_235f ; music related
+ call Func_2312 ; music related
+.restoreRomBank
+ pop af
+ ld [H_LOADEDROMBANK],a
+ ld [$2000],a
+ ret
+
+LoadScreenRelatedData:: ; 0f0c (0:0f0c)
+ call LoadTileBlockMap
+ call LoadTilesetTilePatternData
+ call LoadCurrentMapView
+ ret
+
+Func_0f16:: ; 0f16 (0:0f16)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ call DisableLCD
+ call ResetMapVariables
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ call LoadScreenRelatedData
+ call CopyMapViewToVRAM
+ ld de,vBGMap1
+ call CopyMapViewToVRAM2
+ call EnableLCD
+ call ReloadMapSpriteTilePatterns
+ pop af
+ call BankswitchCommon
+ jr .asm_0f4d
+Func_0f3d:: ; 0f3d (0:0f3d)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ ld a,[W_CURMAP]
+ call SwitchToMapRomBank
+ call LoadTileBlockMap
+ pop af
+ call BankswitchCommon
+.asm_0f4d
+ ld hl, Func_f02da
+ ld b,BANK(Func_f02da) ; 3c:42da
+ jp Bankswitch
+ ret ; useless?
+
+ResetMapVariables:: ; 0f56 (0:0f56)
+ ld a,$98
+ ld [wMapViewVRAMPointer + 1],a
+ xor a
+ ld [wMapViewVRAMPointer],a
+ ld [hSCY],a
+ ld [hSCX],a
+ ld [wWalkCounter],a
+ ld [wd119],a
+ ld [W_SPRITESETID],a
+ ld [wWalkBikeSurfStateCopy],a
+ ret
+
+CopyMapViewToVRAM:: ; 0f70 (0:0f70)
+; copy current map view to VRAM
+ ld de,vBGMap0
+CopyMapViewToVRAM2: ; 0f73 (0:0f73)
+ ld hl,wTileMap
+ ld b,18
+.vramCopyLoop
+ ld c,20
+.vramCopyInnerLoop
+ ld a,[hli]
+ ld [de],a
+ inc e
+ dec c
+ jr nz,.vramCopyInnerLoop
+ ld a,32 - 20 ; total vram map width in tiles - screen width in tiles
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry
+ dec b
+ jr nz,.vramCopyLoop
+ ret
+
+; function to switch to the ROM bank that a map is stored in
+; Input: a = map number
+SwitchToMapRomBank:: ; 0f8b (0:0f8b)
+ push hl
+ push bc
+ ld c,a
+ ld b,$00
+ ld a,BANK(MapHeaderBanks)
+ call BankswitchHome ; switch to ROM bank 3F
+ ld hl,MapHeaderBanks
+ add hl,bc
+ ld a,[hl]
+ ld [$ffe8],a ; save map ROM bank
+ call BankswitchCommon
+ pop bc
+ pop hl
+ ret
+
+GetMapHeaderPointer:: ; 0fa7 (0:0fa7)
+ ld a,[H_LOADEDROMBANK]
+ push af
+ switchbank Pointer_fc1f2 ; 3f:41f2
+ push de
+ ld a,[W_CURMAP]
+ ld e,a
+ ld d,$0
+ ld hl,Pointer_fc1f2
+ add hl,de
+ add hl,de
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ pop de
+ pop af
+ jp BankswitchCommon
+
+IgnoreInputForHalfSecond: ; 0fc3 (0:0fc3)
+ ld a, 30
+ ld [wIgnoreInputCounter], a
+ ld hl, wd730
+ ld a, [hl]
+ or $26
+ ld [hl], a ; set ignore input bit
+ ret
+
+ResetUsingStrengthOutOfBattleBit: ; 0fd0 (0:0fd0)
+ ld hl, wd728
+ res 0, [hl]
+ ret
+
+ForceBikeOrSurf:: ; 0fd6 (0:0fd6)
+ ld b, BANK(RedSprite)
+ ld hl, LoadPlayerSpriteGraphics
+ call Bankswitch
+ jp PlayDefaultMusic ; update map/player state?
+
+; Handle the player jumping down
+; a ledge in the overworld.
+HandleMidJump:: ; 0fe1 (0:0fe1)
+ ld a,[wd736]
+ bit 7,a ; jumping down a ledge?
+ ret z
+ ld b, BANK(_HandleMidJump)
+ ld hl, _HandleMidJump
+ jp Bankswitch
+
+IsSpinning:: ; 0ff0 (0:0ff0)
+ ld a,[wd736]
+ bit 7,a
+ ret z ; no spinning
+ ld b, BANK(LoadSpinnerArrowTiles); spin while moving
+ ld hl,LoadSpinnerArrowTiles ; 11:5077
+ jp Bankswitch
+
+Func_0ffe:: ; 0ffe (0:0ffe)
+ ld hl, Func_fcf0c ; 3f:4f0c
+ ld b, BANK(Func_fcf0c)
+ jp Bankswitch
+
+InitSprites:: ; 1006 (0:1006)
+ ld a,[hli]
+ ld [W_NUMSPRITES],a ; save the number of sprites
+ push hl
+ push hl
+ push de
+ push bc
+ call ZeroSpriteStateData
+ call DisableRegularSprites
+ ld hl,W_MAPSPRITEDATA
+ ld bc,$20
+ xor a
+ call FillMemory
+ pop bc
+ pop de
+ pop hl
+ ld a,[W_NUMSPRITES]
+ and a ; are sprites existant?
+ ret z ; don't copy sprite data if not
+ ld b,a
+ ld c,$0
+ ld de,wSpriteStateData1 + $10
+; copy sprite stuff?
+.loadSpriteLoop
+ ld a,[hli]
+ ld [de],a ; store picture ID at C1X0
+ inc d
+ ld a,$04
+ add e
+ ld e,a
+ ld a,[hli]
+ ld [de],a ; store Y position at C2X4
+ inc e
+ ld a,[hli]
+ ld [de],a ; store X position at C2X5
+ inc e
+ ld a,[hli]
+ ld [de],a ; store movement byte 1 at C2X6
+ ld a,[hli]
+ ld [$ff8d],a ; save movement byte 2
+ ld a,[hli]
+ ld [$ff8e],a ; save text ID and flags byte
+ push bc
+ call LoadSprite
+ pop bc
+ dec d
+ ld a,e
+ add a,$a
+ ld e,a
+ inc c
+ inc c
+ dec b
+ jr nz,.loadSpriteLoop
+ ret
+
+ZeroSpriteStateData:: ; 1050 (0:1050)
+; zero C110-C1EF and C210-C2EF
+; C1F0-C1FF and C2F0-C2FF is probably used for Pikachu
+ ld hl,wSpriteStateData1 + $10
+ ld de,wSpriteStateData2 + $10
+ xor a
+ ld b,$e0
+.loop
+ ld [hli],a
+ ld [de],a
+ inc e
+ dec b
+ jr nz,.loop
+ ret
+
+DisableRegularSprites:: ; 1060 (0:1060)
+; initialize all C100-C1FF sprite entries to disabled (other than player's and pikachu)
+ ld hl,wSpriteStateData1 + $12
+ ld de,$10
+ ld c,$e
+.loop
+ ld [hl],$ff
+ add hl,de
+ dec c
+ jr nz,.loop
+ ret
+
+LoadSprite:: ; 106f (0:106f)
+ push hl
+ ld b,$0
+ ld hl,W_MAPSPRITEDATA
+ add hl,bc
+ ld a,[$ff8d]
+ ld [hli],a ; store movement byte 2 in byte 0 of sprite entry
+ ld a,[$ff8e]
+ ld [hl],a ; this appears pointless, since the value is overwritten immediately after
+ ld a,[$ff8e]
+ ld [$ff8d],a
+ and a,$3f
+ ld [hl],a ; store text ID in byte 1 of sprite entry
+ pop hl
+ ld a,[$ff8d]
+ bit 6,a
+ jr nz,.trainerSprite
+ bit 7,a
+ jr nz,.itemBallSprite
+; for regular sprites
+ push hl
+ ld hl,W_MAPSPRITEEXTRADATA
+ add hl,bc
+; zero both bytes, since regular sprites don't use this extra space
+ xor a
+ ld [hli],a
+ ld [hl],a
+ pop hl
+ ret
+
+.trainerSprite
+ ld a,[hli]
+ ld [$ff8d],a ; save trainer class
+ ld a,[hli]
+ ld [$ff8e],a ; save trainer number (within class)
+ push hl
+ ld hl,W_MAPSPRITEEXTRADATA
+ add hl,bc
+ ld a,[$ff8d]
+ ld [hli],a ; store trainer class in byte 0 of the entry
+ ld a,[$ff8e]
+ ld [hl],a ; store trainer number in byte 1 of the entry
+ pop hl
+ ret
+
+.itemBallSprite
+ ld a,[hli]
+ ld [$ff8d],a ; save item number
+ push hl
+ ld hl,W_MAPSPRITEEXTRADATA
+ add hl,bc
+ ld a,[$ff8d]
+ ld [hli],a ; store item number in byte 0 of the entry
+ xor a
+ ld [hl],a ; zero byte 1, since it is not used
+ pop hl
+ ret ; end of home/overworld.asm = 10b9 (0:10b9)
\ No newline at end of file @@ -1,569 +1,600 @@ - -text EQUS "db $00," ; Start writing text. -next EQUS "db $4e," ; Move a line down. -line EQUS "db $4f," ; Start writing at the bottom line. -para EQUS "db $51," ; Start a new paragraph. -cont EQUS "db $55," ; Scroll to the next line. -done EQUS "db $57" ; End a text box. -prompt EQUS "db $58" ; Prompt the player to end a text box (initiating some other event). - -page EQUS "db $49," ; Start a new Pokedex page. -dex EQUS "db $5f, $50" ; End a Pokedex entry. - - -percent EQUS "* $ff / 100" - - -; Constant enumeration is useful for monsters, items, moves, etc. -const_def: MACRO -const_value = 0 -ENDM - -const: MACRO -\1 EQU const_value -const_value = const_value + 1 -ENDM - - -homecall_jump: MACRO - ld a, [H_LOADEDROMBANK] - push af - ld a, BANK(\1) - call BankswitchCommon - call \1 - pop af - jp BankswitchCommon - ENDM - -callba: MACRO - ld b, BANK(\1) - ld hl, \1 - call Bankswitch - ENDM - -callab: MACRO - ld hl, \1 - ld b, BANK(\1) - call Bankswitch - ENDM - -bcd2: MACRO - dn ((\1) / 1000) % 10, ((\1) / 100) % 10 - dn ((\1) / 10) % 10, (\1) % 10 - ENDM - -bcd3: MACRO - dn ((\1) / 100000) % 10, ((\1) / 10000) % 10 - dn ((\1) / 1000) % 10, ((\1) / 100) % 10 - dn ((\1) / 10) % 10, (\1) % 10 - ENDM - -coins equs "bcd2" -money equs "bcd3" - -;\1 = X -;\2 = Y -hlCoord: MACRO - ld hl, wTileMap + 20 * \2 + \1 - ENDM - -;\1 = X -;\2 = Y -deCoord: MACRO - ld de, wTileMap + 20 * \2 + \1 - ENDM - -;\1 = X -;\2 = Y -bcCoord: MACRO - ld bc, wTileMap + 20 * \2 + \1 - ENDM - -;\1 = X -;\2 = Y -aCoord: MACRO - ld a, [wTileMap + 20 * \2 + \1] - ENDM - -;\1 = X -;\2 = Y -Coorda: MACRO - ld [wTileMap + 20 * \2 + \1], a - ENDM - -;\1 = X -;\2 = Y -dwCoord: MACRO - dw wTileMap + 20 * \2 + \1 - ENDM - -;\1 = Map Width -;\2 = Rows above (Y-blocks) -;\3 = X movement (X-blocks) -EVENT_DISP: MACRO - dw (wOverworldMap + 7 + (\1) + ((\1) + 6) * ((\2) >> 1) + ((\3) >> 1)) ; Ev.Disp - db \2,\3 ;Y,X - ENDM - -FLYWARP_DATA: MACRO - EVENT_DISP \1,\2,\3 - db ((\2) & $01) ;sub-block Y - db ((\3) & $01) ;sub-block X - ENDM - -; external map entry macro -EMAP: MACRO ; emap x-coordinate,y-coordinate,textpointer -; the appearance of towns and routes in the town map, indexed by map id - ; nybble: y-coordinate - ; nybble: x-coordinate - ; word : pointer to map name - db (\1 + (\2 << 4)) - dw \3 - ENDM - -; internal map entry macro -IMAP: MACRO ; imap mapid_less_than,x-coordinate,y-coordinate,textpointer -; the appearance of buildings and dungeons in the town map - ; byte : maximum map id subject to this rule - ; nybble: y-coordinate - ; nybble: x-coordinate - ; word : pointer to map name - db \1 - db \2 + \3 << 4 - dw \4 - ENDM - -; tilesets' headers macro -tileset: MACRO - db BANK(\2) ; BANK(GFX) - dw \1, \2, \3 ; Block, GFX, Coll - db \4, \5, \6 ; counter tiles - db \7 ; grass tile - db \8 ; permission (indoor, cave, outdoor) - ENDM - -INDOOR EQU 0 -CAVE EQU 1 -OUTDOOR EQU 2 - -; macro for two nibbles -dn: MACRO - db (\1 << 4 | \2) - ENDM - -; macro for putting a byte then a word -dbw: MACRO - db \1 - dw \2 - ENDM - -; data format macros -RGB: MACRO - dw (\3 << 10 | \2 << 5 | \1) - ENDM - -; text macros -TX_NUM: MACRO -; print a big-endian decimal number. -; \1: address to read from -; \2: number of bytes to read -; \3: number of digits to display - db $09 - dw \1 - db \2 << 4 | \3 - ENDM - -TX_FAR: MACRO - db $17 - dw \1 - db BANK(\1) - ENDM - -; text engine command $1 -TX_RAM: MACRO -; prints text to screen -; \1: RAM address to read from - db $1 - dw \1 - ENDM - -TX_BCD: MACRO - db $2 - dw \1 - db \2 - ENDM - -; Predef macro. -add_predef: MACRO -\1Predef:: - db BANK(\1) - dw \1 - ENDM - -predef_id: MACRO - ld a, (\1Predef - PredefPointers) / 3 - ENDM - -predef: MACRO - predef_id \1 - call Predef - ENDM - -predef_jump: MACRO - predef_id \1 - jp Predef - ENDM - - -add_tx_pre: MACRO -\1_id:: dw \1 -ENDM - -tx_pre_id: MACRO - ld a, (\1_id - TextPredefs) / 2 -ENDM - -tx_pre: MACRO - tx_pre_id \1 - call PrintPredefTextID -ENDM - -tx_pre_jump: MACRO - tx_pre_id \1 - jp PrintPredefTextID -ENDM - - -;1_channel EQU $00 -;2_channels EQU $40 -;3_channels EQU $80 -;4_channels EQU $C0 - -CH0 EQU 0 -CH1 EQU 1 -CH2 EQU 2 -CH3 EQU 3 -CH4 EQU 4 -CH5 EQU 5 -CH6 EQU 6 -CH7 EQU 7 - -unknownsfx0x10: MACRO - db $10 - db \1 -ENDM - -unknownsfx0x20: MACRO - db $20 | \1 - db \2 - db \3 - db \4 -ENDM - -unknownnoise0x20: MACRO - db $20 | \1 - db \2 - db \3 -ENDM - -;format: pitch length (in 16ths) -C_: MACRO - db $00 | (\1 - 1) -ENDM - -C#: MACRO - db $10 | (\1 - 1) -ENDM - -D_: MACRO - db $20 | (\1 - 1) -ENDM - -D#: MACRO - db $30 | (\1 - 1) -ENDM - -E_: MACRO - db $40 | (\1 - 1) -ENDM - -F_: MACRO - db $50 | (\1 - 1) -ENDM - -F#: MACRO - db $60 | (\1 - 1) -ENDM - -G_: MACRO - db $70 | (\1 - 1) -ENDM - -G#: MACRO - db $80 | (\1 - 1) -ENDM - -A_: MACRO - db $90 | (\1 - 1) -ENDM - -A#: MACRO - db $A0 | (\1 - 1) -ENDM - -B_: MACRO - db $B0 | (\1 - 1) -ENDM - -;format: instrument length (in 16ths) -snare1: MACRO - db $B0 | (\1 - 1) - db $01 -ENDM - -snare2: MACRO - db $B0 | (\1 - 1) - db $02 -ENDM - -snare3: MACRO - db $B0 | (\1 - 1) - db $03 -ENDM - -snare4: MACRO - db $B0 | (\1 - 1) - db $04 -ENDM - -snare5: MACRO - db $B0 | (\1 - 1) - db $05 -ENDM - -triangle1: MACRO - db $B0 | (\1 - 1) - db $06 -ENDM - -triangle2: MACRO - db $B0 | (\1 - 1) - db $07 -ENDM - -snare6: MACRO - db $B0 | (\1 - 1) - db $08 -ENDM - -snare7: MACRO - db $B0 | (\1 - 1) - db $09 -ENDM - -snare8: MACRO - db $B0 | (\1 - 1) - db $0A -ENDM - -snare9: MACRO - db $B0 | (\1 - 1) - db $0B -ENDM - -cymbal1: MACRO - db $B0 | (\1 - 1) - db $0C -ENDM - -cymbal2: MACRO - db $B0 | (\1 - 1) - db $0D -ENDM - -cymbal3: MACRO - db $B0 | (\1 - 1) - db $0E -ENDM - -mutedsnare1: MACRO - db $B0 | (\1 - 1) - db $0F -ENDM - -triangle3: MACRO - db $B0 | (\1 - 1) - db $10 -ENDM - -mutedsnare2: MACRO - db $B0 | (\1 - 1) - db $11 -ENDM - -mutedsnare3: MACRO - db $B0 | (\1 - 1) - db $12 -ENDM - -mutedsnare4: MACRO - db $B0 | (\1 - 1) - db $13 -ENDM - -;format: rest length (in 16ths) -rest: MACRO - db $C0 | (\1 - 1) -ENDM - -; format: notetype speed, volume, fade -notetype: MACRO - db $D0 | \1 - db (\2 << 4) | \3 -ENDM - -dspeed: MACRO - db $D0 | \1 -ENDM - -octave: MACRO - db $E8 - \1 -ENDM - -toggleperfectpitch: MACRO - db $E8 -ENDM - -;format: vibrato delay, rate, depth -vibrato: MACRO - db $EA - db \1 - db (\2 << 4) | \3 -ENDM - -pitchbend: MACRO - db $EB - db \1 - db \2 -ENDM - -duty: MACRO - db $EC - db \1 -ENDM - -tempo: MACRO - db $ED - db \1 / $100 - db \1 % $100 -ENDM - -stereopanning: MACRO - db $EE - db \1 -ENDM - -volume: MACRO - db $F0 - db (\1 << 4) | \2 -ENDM - -executemusic: MACRO - db $F8 -ENDM - -dutycycle: MACRO - db $FC - db \1 -ENDM - -;format: callchannel address -callchannel: MACRO - db $FD - dw \1 -ENDM - -;format: loopchannel count, address -loopchannel: MACRO - db $FE - db \1 - dw \2 -ENDM - -endchannel: MACRO - db $FF -ENDM - - -;\1 (byte) = connected map id -;\2 (byte) = connected map width -;\3 (byte) = connected map height -;\4 (byte) = x movement of connection strip -;\5 (byte) = connection strip offset -;\6 (byte) = width of connection strip -;\7 (word) = connected map blocks pointer -NORTH_MAP_CONNECTION: MACRO - db \1 ; map id - dw \7 + (\2 * (\3 - 3)) + \5; "Connection Strip" location - dw wOverworldMap + 3 + \4 ; current map position - db \6 ; width of connection strip - db \2 ; map width - db (\3 * 2) - 1 ; y alignment (y coordinate of player when entering map) - db (\4 - \5) * -2 ; x alignment (x coordinate of player when entering map) - dw wOverworldMap + 1 + (\3 * (\2 + 6)) ; window (position of the upper left block after entering the map) -ENDM - -;\1 (byte) = connected map id -;\2 (byte) = connected map width -;\3 (byte) = x movement of connection strip -;\4 (byte) = connection strip offset -;\5 (byte) = width of connection strip -;\6 (word) = connected map blocks pointer -;\7 (byte) = current map width -;\8 (byte) = current map height -SOUTH_MAP_CONNECTION: MACRO - db \1 ; map id - dw \6 + \4 ; "Conection Strip" location - dw wOverworldMap + 3 + (\8 + 3) * (\7 + 6) + \3 ; current map positoin - db \5 ; width of connection strip - db \2 ; map width - db 0 ; y alignment (y coordinate of player when entering map) - db (\3 - \4) * -2 ; x alignment (x coordinate of player when entering map) - dw wOverworldMap + 7 + \2 ; window (position of the upper left block after entering the map) -ENDM - -;\1 (byte) = connected map id -;\2 (byte) = connected map width -;\3 (byte) = y movement of connection strip -;\4 (byte) = connection strip offset -;\5 (byte) = height of connection strip -;\6 (word) = connected map blocks pointer -;\7 (byte) = current map width -EAST_MAP_CONNECTION: MACRO - db \1 ; map id - dw \6 + (\2 * \4) ; "Connection Strip" location - dw wOverworldMap - 3 + (\7 + 6) * (\3 + 4) ; current map position - db \5 ; height of connection strip - db \2 ; map width - db (\3 - \4) * -2 ; y alignment - db 0 ; x alignment - dw wOverworldMap + 7 + \2 ; window (position of the upper left block after entering the map) -ENDM - -;\1 (byte) = connected map id -;\2 (byte) = connected map width -;\3 (byte) = y movement of connection strip -;\4 (byte) = connection strip offset -;\5 (byte) = height of connection strip -;\6 (word) = connected map blocks pointer -;\7 (byte) = current map width -WEST_MAP_CONNECTION: MACRO - db \1 ; map id - dw \6 + (\2 * \4) + \2 - 3 ; "Connection Strip" location - dw wOverworldMap + (\7 + 6) * (\3 + 3) ; current map position - db \5 ; height of connection strip - db \2 ; map width - db (\3 - \4) * -2 ; y alignment - db (\2 * 2) - 1 ; x alignment - dw wOverworldMap + 6 + (2 * \2) ; window (position of the upper left block after entring the map) -ENDM +
+text EQUS "db $00," ; Start writing text.
+next EQUS "db $4e," ; Move a line down.
+line EQUS "db $4f," ; Start writing at the bottom line.
+para EQUS "db $51," ; Start a new paragraph.
+cont EQUS "db $55," ; Scroll to the next line.
+done EQUS "db $57" ; End a text box.
+prompt EQUS "db $58" ; Prompt the player to end a text box (initiating some other event).
+
+page EQUS "db $49," ; Start a new Pokedex page.
+dex EQUS "db $5f, $50" ; End a Pokedex entry.
+
+
+percent EQUS "* $ff / 100"
+
+
+; Constant enumeration is useful for monsters, items, moves, etc.
+const_def: MACRO
+const_value = 0
+ENDM
+
+const: MACRO
+\1 EQU const_value
+const_value = const_value + 1
+ENDM
+
+
+homecall_jump: MACRO
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, BANK(\1)
+ call BankswitchCommon
+ call \1
+ pop af
+ jp BankswitchCommon
+ ENDM
+
+homecall: MACRO
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, BANK(\1)
+ call BankswitchCommon
+ call \1
+ pop af
+ call BankswitchCommon
+ ENDM
+
+homecall_sf: MACRO ; homecall but save flags by popping into bc instead of af
+ ld a, [H_LOADEDROMBANK]
+ push af
+ ld a, BANK(\1)
+ call BankswitchCommon
+ call \1
+ pop bc
+ ld a,b
+ call BankswitchCommon
+ ENDM
+
+switchbank: MACRO
+ ld a, BANK(\1)
+ call BankswitchCommon
+ ENDM
+
+callsb: MACRO
+ ld a, BANK(\1)
+ call BankswitchCommon
+ call \1
+
+callba: MACRO
+ ld b, BANK(\1)
+ ld hl, \1
+ call Bankswitch
+ ENDM
+
+callab: MACRO
+ ld hl, \1
+ ld b, BANK(\1)
+ call Bankswitch
+ ENDM
+
+bcd2: MACRO
+ dn ((\1) / 1000) % 10, ((\1) / 100) % 10
+ dn ((\1) / 10) % 10, (\1) % 10
+ ENDM
+
+bcd3: MACRO
+ dn ((\1) / 100000) % 10, ((\1) / 10000) % 10
+ dn ((\1) / 1000) % 10, ((\1) / 100) % 10
+ dn ((\1) / 10) % 10, (\1) % 10
+ ENDM
+
+coins equs "bcd2"
+money equs "bcd3"
+
+;\1 = X
+;\2 = Y
+hlCoord: MACRO
+ ld hl, wTileMap + 20 * \2 + \1
+ ENDM
+
+;\1 = X
+;\2 = Y
+deCoord: MACRO
+ ld de, wTileMap + 20 * \2 + \1
+ ENDM
+
+;\1 = X
+;\2 = Y
+bcCoord: MACRO
+ ld bc, wTileMap + 20 * \2 + \1
+ ENDM
+
+;\1 = X
+;\2 = Y
+aCoord: MACRO
+ ld a, [wTileMap + 20 * \2 + \1]
+ ENDM
+
+;\1 = X
+;\2 = Y
+Coorda: MACRO
+ ld [wTileMap + 20 * \2 + \1], a
+ ENDM
+
+;\1 = X
+;\2 = Y
+dwCoord: MACRO
+ dw wTileMap + 20 * \2 + \1
+ ENDM
+
+;\1 = Map Width
+;\2 = Rows above (Y-blocks)
+;\3 = X movement (X-blocks)
+EVENT_DISP: MACRO
+ dw (wOverworldMap + 7 + (\1) + ((\1) + 6) * ((\2) >> 1) + ((\3) >> 1)) ; Ev.Disp
+ db \2,\3 ;Y,X
+ ENDM
+
+FLYWARP_DATA: MACRO
+ EVENT_DISP \1,\2,\3
+ db ((\2) & $01) ;sub-block Y
+ db ((\3) & $01) ;sub-block X
+ ENDM
+
+; external map entry macro
+EMAP: MACRO ; emap x-coordinate,y-coordinate,textpointer
+; the appearance of towns and routes in the town map, indexed by map id
+ ; nybble: y-coordinate
+ ; nybble: x-coordinate
+ ; word : pointer to map name
+ db (\1 + (\2 << 4))
+ dw \3
+ ENDM
+
+; internal map entry macro
+IMAP: MACRO ; imap mapid_less_than,x-coordinate,y-coordinate,textpointer
+; the appearance of buildings and dungeons in the town map
+ ; byte : maximum map id subject to this rule
+ ; nybble: y-coordinate
+ ; nybble: x-coordinate
+ ; word : pointer to map name
+ db \1
+ db \2 + \3 << 4
+ dw \4
+ ENDM
+
+; tilesets' headers macro
+tileset: MACRO
+ db BANK(\2) ; BANK(GFX)
+ dw \1, \2, \3 ; Block, GFX, Coll
+ db \4, \5, \6 ; counter tiles
+ db \7 ; grass tile
+ db \8 ; permission (indoor, cave, outdoor)
+ ENDM
+
+INDOOR EQU 0
+CAVE EQU 1
+OUTDOOR EQU 2
+
+; macro for two nibbles
+dn: MACRO
+ db (\1 << 4 | \2)
+ ENDM
+
+; macro for putting a byte then a word
+dbw: MACRO
+ db \1
+ dw \2
+ ENDM
+
+; data format macros
+RGB: MACRO
+ dw (\3 << 10 | \2 << 5 | \1)
+ ENDM
+
+; text macros
+TX_NUM: MACRO
+; print a big-endian decimal number.
+; \1: address to read from
+; \2: number of bytes to read
+; \3: number of digits to display
+ db $09
+ dw \1
+ db \2 << 4 | \3
+ ENDM
+
+TX_FAR: MACRO
+ db $17
+ dw \1
+ db BANK(\1)
+ ENDM
+
+; text engine command $1
+TX_RAM: MACRO
+; prints text to screen
+; \1: RAM address to read from
+ db $1
+ dw \1
+ ENDM
+
+TX_BCD: MACRO
+ db $2
+ dw \1
+ db \2
+ ENDM
+
+; Predef macro.
+add_predef: MACRO
+\1Predef::
+ db BANK(\1)
+ dw \1
+ ENDM
+
+predef_id: MACRO
+ ld a, (\1Predef - PredefPointers) / 3
+ ENDM
+
+predef: MACRO
+ predef_id \1
+ call Predef
+ ENDM
+
+predef_jump: MACRO
+ predef_id \1
+ jp Predef
+ ENDM
+
+
+add_tx_pre: MACRO
+\1_id:: dw \1
+ENDM
+
+tx_pre_id: MACRO
+ ld a, (\1_id - TextPredefs) / 2
+ENDM
+
+tx_pre: MACRO
+ tx_pre_id \1
+ call PrintPredefTextID
+ENDM
+
+tx_pre_jump: MACRO
+ tx_pre_id \1
+ jp PrintPredefTextID
+ENDM
+
+
+;1_channel EQU $00
+;2_channels EQU $40
+;3_channels EQU $80
+;4_channels EQU $C0
+
+CH0 EQU 0
+CH1 EQU 1
+CH2 EQU 2
+CH3 EQU 3
+CH4 EQU 4
+CH5 EQU 5
+CH6 EQU 6
+CH7 EQU 7
+
+unknownsfx0x10: MACRO
+ db $10
+ db \1
+ENDM
+
+unknownsfx0x20: MACRO
+ db $20 | \1
+ db \2
+ db \3
+ db \4
+ENDM
+
+unknownnoise0x20: MACRO
+ db $20 | \1
+ db \2
+ db \3
+ENDM
+
+;format: pitch length (in 16ths)
+C_: MACRO
+ db $00 | (\1 - 1)
+ENDM
+
+C#: MACRO
+ db $10 | (\1 - 1)
+ENDM
+
+D_: MACRO
+ db $20 | (\1 - 1)
+ENDM
+
+D#: MACRO
+ db $30 | (\1 - 1)
+ENDM
+
+E_: MACRO
+ db $40 | (\1 - 1)
+ENDM
+
+F_: MACRO
+ db $50 | (\1 - 1)
+ENDM
+
+F#: MACRO
+ db $60 | (\1 - 1)
+ENDM
+
+G_: MACRO
+ db $70 | (\1 - 1)
+ENDM
+
+G#: MACRO
+ db $80 | (\1 - 1)
+ENDM
+
+A_: MACRO
+ db $90 | (\1 - 1)
+ENDM
+
+A#: MACRO
+ db $A0 | (\1 - 1)
+ENDM
+
+B_: MACRO
+ db $B0 | (\1 - 1)
+ENDM
+
+;format: instrument length (in 16ths)
+snare1: MACRO
+ db $B0 | (\1 - 1)
+ db $01
+ENDM
+
+snare2: MACRO
+ db $B0 | (\1 - 1)
+ db $02
+ENDM
+
+snare3: MACRO
+ db $B0 | (\1 - 1)
+ db $03
+ENDM
+
+snare4: MACRO
+ db $B0 | (\1 - 1)
+ db $04
+ENDM
+
+snare5: MACRO
+ db $B0 | (\1 - 1)
+ db $05
+ENDM
+
+triangle1: MACRO
+ db $B0 | (\1 - 1)
+ db $06
+ENDM
+
+triangle2: MACRO
+ db $B0 | (\1 - 1)
+ db $07
+ENDM
+
+snare6: MACRO
+ db $B0 | (\1 - 1)
+ db $08
+ENDM
+
+snare7: MACRO
+ db $B0 | (\1 - 1)
+ db $09
+ENDM
+
+snare8: MACRO
+ db $B0 | (\1 - 1)
+ db $0A
+ENDM
+
+snare9: MACRO
+ db $B0 | (\1 - 1)
+ db $0B
+ENDM
+
+cymbal1: MACRO
+ db $B0 | (\1 - 1)
+ db $0C
+ENDM
+
+cymbal2: MACRO
+ db $B0 | (\1 - 1)
+ db $0D
+ENDM
+
+cymbal3: MACRO
+ db $B0 | (\1 - 1)
+ db $0E
+ENDM
+
+mutedsnare1: MACRO
+ db $B0 | (\1 - 1)
+ db $0F
+ENDM
+
+triangle3: MACRO
+ db $B0 | (\1 - 1)
+ db $10
+ENDM
+
+mutedsnare2: MACRO
+ db $B0 | (\1 - 1)
+ db $11
+ENDM
+
+mutedsnare3: MACRO
+ db $B0 | (\1 - 1)
+ db $12
+ENDM
+
+mutedsnare4: MACRO
+ db $B0 | (\1 - 1)
+ db $13
+ENDM
+
+;format: rest length (in 16ths)
+rest: MACRO
+ db $C0 | (\1 - 1)
+ENDM
+
+; format: notetype speed, volume, fade
+notetype: MACRO
+ db $D0 | \1
+ db (\2 << 4) | \3
+ENDM
+
+dspeed: MACRO
+ db $D0 | \1
+ENDM
+
+octave: MACRO
+ db $E8 - \1
+ENDM
+
+toggleperfectpitch: MACRO
+ db $E8
+ENDM
+
+;format: vibrato delay, rate, depth
+vibrato: MACRO
+ db $EA
+ db \1
+ db (\2 << 4) | \3
+ENDM
+
+pitchbend: MACRO
+ db $EB
+ db \1
+ db \2
+ENDM
+
+duty: MACRO
+ db $EC
+ db \1
+ENDM
+
+tempo: MACRO
+ db $ED
+ db \1 / $100
+ db \1 % $100
+ENDM
+
+stereopanning: MACRO
+ db $EE
+ db \1
+ENDM
+
+volume: MACRO
+ db $F0
+ db (\1 << 4) | \2
+ENDM
+
+executemusic: MACRO
+ db $F8
+ENDM
+
+dutycycle: MACRO
+ db $FC
+ db \1
+ENDM
+
+;format: callchannel address
+callchannel: MACRO
+ db $FD
+ dw \1
+ENDM
+
+;format: loopchannel count, address
+loopchannel: MACRO
+ db $FE
+ db \1
+ dw \2
+ENDM
+
+endchannel: MACRO
+ db $FF
+ENDM
+
+
+;\1 (byte) = connected map id
+;\2 (byte) = connected map width
+;\3 (byte) = connected map height
+;\4 (byte) = x movement of connection strip
+;\5 (byte) = connection strip offset
+;\6 (byte) = width of connection strip
+;\7 (word) = connected map blocks pointer
+NORTH_MAP_CONNECTION: MACRO
+ db \1 ; map id
+ dw \7 + (\2 * (\3 - 3)) + \5; "Connection Strip" location
+ dw wOverworldMap + 3 + \4 ; current map position
+ db \6 ; width of connection strip
+ db \2 ; map width
+ db (\3 * 2) - 1 ; y alignment (y coordinate of player when entering map)
+ db (\4 - \5) * -2 ; x alignment (x coordinate of player when entering map)
+ dw wOverworldMap + 1 + (\3 * (\2 + 6)) ; window (position of the upper left block after entering the map)
+ENDM
+
+;\1 (byte) = connected map id
+;\2 (byte) = connected map width
+;\3 (byte) = x movement of connection strip
+;\4 (byte) = connection strip offset
+;\5 (byte) = width of connection strip
+;\6 (word) = connected map blocks pointer
+;\7 (byte) = current map width
+;\8 (byte) = current map height
+SOUTH_MAP_CONNECTION: MACRO
+ db \1 ; map id
+ dw \6 + \4 ; "Conection Strip" location
+ dw wOverworldMap + 3 + (\8 + 3) * (\7 + 6) + \3 ; current map positoin
+ db \5 ; width of connection strip
+ db \2 ; map width
+ db 0 ; y alignment (y coordinate of player when entering map)
+ db (\3 - \4) * -2 ; x alignment (x coordinate of player when entering map)
+ dw wOverworldMap + 7 + \2 ; window (position of the upper left block after entering the map)
+ENDM
+
+;\1 (byte) = connected map id
+;\2 (byte) = connected map width
+;\3 (byte) = y movement of connection strip
+;\4 (byte) = connection strip offset
+;\5 (byte) = height of connection strip
+;\6 (word) = connected map blocks pointer
+;\7 (byte) = current map width
+EAST_MAP_CONNECTION: MACRO
+ db \1 ; map id
+ dw \6 + (\2 * \4) ; "Connection Strip" location
+ dw wOverworldMap - 3 + (\7 + 6) * (\3 + 4) ; current map position
+ db \5 ; height of connection strip
+ db \2 ; map width
+ db (\3 - \4) * -2 ; y alignment
+ db 0 ; x alignment
+ dw wOverworldMap + 7 + \2 ; window (position of the upper left block after entering the map)
+ENDM
+
+;\1 (byte) = connected map id
+;\2 (byte) = connected map width
+;\3 (byte) = y movement of connection strip
+;\4 (byte) = connection strip offset
+;\5 (byte) = height of connection strip
+;\6 (word) = connected map blocks pointer
+;\7 (byte) = current map width
+WEST_MAP_CONNECTION: MACRO
+ db \1 ; map id
+ dw \6 + (\2 * \4) + \2 - 3 ; "Connection Strip" location
+ dw wOverworldMap + (\7 + 6) * (\3 + 3) ; current map position
+ db \5 ; height of connection strip
+ db \2 ; map width
+ db (\3 - \4) * -2 ; y alignment
+ db (\2 * 2) - 1 ; x alignment
+ dw wOverworldMap + 6 + (2 * \2) ; window (position of the upper left block after entring the map)
+ENDM
@@ -1,6684 +1,6684 @@ -INCLUDE "constants.asm" - -NPC_SPRITES_1 EQU $4 -NPC_SPRITES_2 EQU $5 - -GFX EQU $4 - -PICS_1 EQU $9 -PICS_2 EQU $A -PICS_3 EQU $B -PICS_4 EQU $C -PICS_5 EQU $D - - -INCLUDE "home.asm" - - -SECTION "bank1",ROMX,BANK[$1] - -INCLUDE "data/facing.asm" - -ResetStatusAndHalveMoneyOnBlackout:: -; Reset player status on blackout. - xor a - ld [wBattleResult], a - ld [wWalkBikeSurfState], a - ld [W_ISINBATTLE], a - ld [wMapPalOffset], a - ld [wNPCMovementScriptFunctionNum], a - ld [hJoyHeld], a - ld [wNPCMovementScriptPointerTableNum], a - ld [wFlags_0xcd60], a - - ld [$ff9f], a - ld [$ff9f + 1], a - ld [$ff9f + 2], a - call HasEnoughMoney - jr c, .lostmoney ; never happens - - ; Halve the player's money. - ld a, [wPlayerMoney] - ld [$ff9f], a - ld a, [wPlayerMoney + 1] - ld [$ff9f + 1], a - ld a, [wPlayerMoney + 2] - ld [$ff9f + 2], a - xor a - ld [$ffa2], a - ld [$ffa3], a - ld a, 2 - ld [$ffa4], a - predef DivideBCDPredef3 - ld a, [$ffa2] - ld [wPlayerMoney], a - ld a, [$ffa2 + 1] - ld [wPlayerMoney + 1], a - ld a, [$ffa2 + 2] - ld [wPlayerMoney + 2], a - -.lostmoney - ld hl, wd732 - set 2, [hl] - res 3, [hl] - set 6, [hl] - ld a, %11111111 - ld [wJoyIgnore], a - predef_jump HealParty - - -MewPicFront:: INCBIN "pic/bmon/mew.pic" -MewPicBack:: INCBIN "pic/monback/mewb.pic" -INCLUDE "data/baseStats/mew.asm" - -INCLUDE "engine/battle/safari_zone.asm" - -INCLUDE "engine/titlescreen.asm" - -NintenText: db "NINTEN@" -SonyText: db "SONY@" - - -LoadMonData_: -; Load monster [wWhichPokemon] from list [wcc49]: -; 0: partymon -; 1: enemymon -; 2: boxmon -; 3: daycaremon -; Return monster id at wcf91 and its data at wLoadedMon. -; Also load base stats at W_MONHDEXNUM for convenience. - - ld a, [wDayCareMonSpecies] - ld [wcf91], a - ld a, [wcc49] - cp 3 - jr z, .GetMonHeader - - ld a, [wWhichPokemon] - ld e, a - callab GetMonSpecies - -.GetMonHeader - ld a, [wcf91] - ld [wd0b5], a ; input for GetMonHeader - call GetMonHeader - - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wcc49] - cp 1 - jr c, .getMonEntry - - ld hl, wEnemyMons - jr z, .getMonEntry - - cp 2 - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 - jr z, .getMonEntry - - ld hl, wDayCareMon - jr .copyMonData - -.getMonEntry - ld a, [wWhichPokemon] - call AddNTimes - -.copyMonData - ld de, wLoadedMon - ld bc, wPartyMon2 - wPartyMon1 - jp CopyData - - -INCLUDE "data/item_prices.asm" -INCLUDE "text/item_names.asm" - -UnusedNames: - db "かみなりバッヂ@" - db "かいがらバッヂ@" - db "おじぞうバッヂ@" - db "はやぶさバッヂ@" - db "ひんやりバッヂ@" - db "なかよしバッヂ@" - db "バラバッヂ@" - db "ひのたまバッヂ@" - db "ゴールドバッヂ@" - db "たまご@" - db "ひよこ@" - db "ブロンズ@" - db "シルバー@" - db "ゴールド@" - db "プチキャプテン@" - db "キャプテン@" - db "プチマスター@" - db "マスター@" - db "エクセレント" - -INCLUDE "engine/overworld/oam.asm" -INCLUDE "engine/oam_dma.asm" - -PrintWaitingText: - hlCoord 3, 10 - ld b, $1 - ld c, $b - ld a, [W_ISINBATTLE] - and a - jr z, .asm_4c17 - call TextBoxBorder - jr .asm_4c1a -.asm_4c17 - call CableClub_TextBoxBorder -.asm_4c1a - hlCoord 4, 11 - ld de, WaitingText - call PlaceString - ld c, 50 - jp DelayFrames - -WaitingText: - db "Waiting...!@" - - -_UpdateSprites: ; 4c34 (1:4c34) - ld h, $c1 - inc h - ld a, $e ; wSpriteStateData2 + $0e -.spriteLoop - ld l, a - sub $e - ld c, a - ld [H_CURRENTSPRITEOFFSET], a - ld a, [hl] - and a - jr z, .skipSprite ; tests $c2Xe - push hl - push de - push bc - call .updateCurrentSprite - pop bc - pop de - pop hl -.skipSprite - ld a, l - add $10 ; move to next sprite - cp $e ; test for overflow (back at $0e) - jr nz, .spriteLoop - ret -.updateCurrentSprite ; 4c54 (1:4c54) - cp $1 - jp nz, UpdateNonPlayerSprite - jp UpdatePlayerSprite - -UpdateNonPlayerSprite: - dec a - swap a - ld [$ff93], a ; $10 * sprite# - ld a, [wNPCMovementScriptSpriteOffset] ; some sprite offset? - ld b, a - ld a, [H_CURRENTSPRITEOFFSET] - cp b - jr nz, .unequal - jp Func_5236 -.unequal - jp Func_4ed1 - -; This detects if the current sprite (whose offset is at H_CURRENTSPRITEOFFSET) -; is going to collide with another sprite by looping over the other sprites. -; The current sprite's offset will be labelled with i (e.g. $c1i0). -; The loop sprite's offset will labelled with j (e.g. $c1j0). -; -; Note that the Y coordinate of the sprite (in [$c1k4]) is one of the following -; 9 values when the sprite is aligned with the grid: $fc, $0c, $1c, $2c, ..., $7c. -; The reason that 4 is added below to the coordinate is to make it align with a -; multiple of $10 to make comparisons easier. -DetectCollisionBetweenSprites: - nop - - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add wSpriteStateData1 % $100 - ld l, a - - ld a, [hl] ; a = [$c1i0] (picture) (0 if slot is unused) - and a ; is this sprite slot slot used? - ret z ; return if not used - - ld a, l - add 3 - ld l, a - - ld a, [hli] ; a = [$c1i3] (delta Y) (-1, 0, or 1) - call SetSpriteCollisionValues - - ld a, [hli] ; a = [$C1i4] (Y screen coordinate) - add 4 ; align with multiple of $10 - -; The effect of the following 3 lines is to -; add 7 to a if moving south or -; subtract 7 from a if moving north. - add b - and $f0 - or c - - ld [$ff90], a ; store Y coordinate adjusted for direction of movement - - ld a, [hli] ; a = [$c1i5] (delta X) (-1, 0, or 1) - call SetSpriteCollisionValues - ld a, [hl] ; a = [$C1i6] (X screen coordinate) - -; The effect of the following 3 lines is to -; add 7 to a if moving east or -; subtract 7 from a if moving west. - add b - and $f0 - or c - - ld [$ff91], a ; store X coordinate adjusted for direction of movement - - ld a, l - add 7 - ld l, a - - xor a - ld [hld], a ; zero [$c1id] XXX what's [$c1id] for? - ld [hld], a ; zero [$c1ic] (directions in which collisions occurred) - - ld a, [$ff91] - ld [hld], a ; [$c1ib] = adjusted X coordiate - ld a, [$ff90] - ld [hl], a ; [$c1ia] = adjusted Y coordinate - - xor a ; zero the loop counter - -.loop - ld [$ff8f], a ; store loop counter - swap a - ld e, a - ld a, [H_CURRENTSPRITEOFFSET] - cp e ; does the loop sprite match the current sprite? - jp z, .next ; go to the next sprite if they match - - ld d, h - ld a, [de] ; a = [$c1j0] (picture) (0 if slot is unused) - and a ; is this sprite slot slot used? - jp z, .next ; go the next sprite if not used - - inc e - inc e - ld a, [de] ; a = [$c1j2] ($ff means the sprite is offscreen) - inc a - jp z, .next ; go the next sprite if offscreen - - ld a, [H_CURRENTSPRITEOFFSET] - add 10 - ld l, a - - inc e - ld a, [de] ; a = [$c1j3] (delta Y) - call SetSpriteCollisionValues - - inc e - ld a, [de] ; a = [$C1j4] (Y screen coordinate) - add 4 ; align with multiple of $10 - -; The effect of the following 3 lines is to -; add 7 to a if moving south or -; subtract 7 from a if moving north. - add b - and $f0 - or c - - sub [hl] ; subtract the adjusted Y coordinate of sprite i ([$c1ia]) from that of sprite j - -; calculate the absolute value of the difference to get the distance - jr nc, .noCarry1 - cpl - inc a -.noCarry1 - ld [$ff90], a ; store the distance between the two sprites' adjusted Y values - -; Use the carry flag set by the above subtraction to determine which sprite's -; Y coordinate is larger. This information is used later to set [$c1ic], -; which stores which direction the collision occurred in. -; The following 5 lines set the lowest 2 bits of c, which are later shifted left by 2. -; If sprite i's Y is larger, set lowest 2 bits of c to 10. -; If sprite j's Y is larger or both are equal, set lowest 2 bits of c to 01. - push af - rl c - pop af - ccf - rl c - -; If sprite i's delta Y is 0, then b = 7, else b = 9. - ld b, 7 - ld a, [hl] ; a = [$c1ia] (adjusted Y coordinate) - and $f - jr z, .next1 - ld b, 9 - -.next1 - ld a, [$ff90] ; a = distance between adjusted Y coordinates - sub b - ld [$ff92], a ; store distance adjusted using sprite i's direction - ld a, b - ld [$ff90], a ; store 7 or 9 depending on sprite i's delta Y - jr c, .checkXDistance - -; If sprite j's delta Y is 0, then b = 7, else b = 9. - ld b, 7 - dec e - ld a, [de] ; a = [$c1j3] (delta Y) - inc e - and a - jr z, .next2 - ld b, 9 - -.next2 - ld a, [$ff92] ; a = distance adjusted using sprite i's direction - sub b ; adjust distance using sprite j's direction - jr z, .checkXDistance - jr nc, .next ; go to next sprite if distance is still positive after both adjustments - -.checkXDistance - inc e - inc l - ld a, [de] ; a = [$c1j5] (delta X) - - push bc - - call SetSpriteCollisionValues - inc e - ld a, [de] ; a = [$c1j6] (X screen coordinate) - -; The effect of the following 3 lines is to -; add 7 to a if moving east or -; subtract 7 from a if moving west. - add b - and $f0 - or c - - pop bc - - sub [hl] ; subtract the adjusted X coordinate of sprite i ([$c1ib]) from that of sprite j - -; calculate the absolute value of the difference to get the distance - jr nc, .noCarry2 - cpl - inc a -.noCarry2 - ld [$ff91], a ; store the distance between the two sprites' adjusted X values - -; Use the carry flag set by the above subtraction to determine which sprite's -; X coordinate is larger. This information is used later to set [$c1ic], -; which stores which direction the collision occurred in. -; The following 5 lines set the lowest 2 bits of c. -; If sprite i's X is larger, set lowest 2 bits of c to 10. -; If sprite j's X is larger or both are equal, set lowest 2 bits of c to 01. - push af - rl c - pop af - ccf - rl c - -; If sprite i's delta X is 0, then b = 7, else b = 9. - ld b, 7 - ld a, [hl] ; a = [$c1ib] (adjusted X coordinate) - and $f - jr z, .next3 - ld b, 9 - -.next3 - ld a, [$ff91] ; a = distance between adjusted X coordinates - sub b - ld [$ff92], a ; store distance adjusted using sprite i's direction - ld a, b - ld [$ff91], a ; store 7 or 9 depending on sprite i's delta X - jr c, .collision - -; If sprite j's delta X is 0, then b = 7, else b = 9. - ld b, 7 - dec e - ld a, [de] ; a = [$c1j5] (delta X) - inc e - and a - jr z, .next4 - ld b, 9 - -.next4 - ld a, [$ff92] ; a = distance adjusted using sprite i's direction - sub b ; adjust distance using sprite j's direction - jr z, .collision - jr nc, .next ; go to next sprite if distance is still positive after both adjustments - -.collision - ld a, [$ff91] ; a = 7 or 9 depending on sprite i's delta X - ld b, a - ld a, [$ff90] ; a = 7 or 9 depending on sprite i's delta Y - inc l - -; If delta X isn't 0 and delta Y is 0, then b = %0011, else b = %1100. -; (note that normally if delta X isn't 0, then delta Y must be 0 and vice versa) - cp b - jr c, .next5 - ld b, %1100 - jr .next6 -.next5 - ld b, %0011 - -.next6 - ld a, c ; c has 2 bits set (one of bits 0-1 is set for the X axis and one of bits 2-3 for the Y axis) - and b ; we select either the bit in bits 0-1 or bits 2-3 based on the calculation immediately above - or [hl] ; or with existing collision direction bits in [$c1ic] - ld [hl], a ; store new value - ld a, c ; useless code because a is overwritten before being used again - -; set bit in [$c1ie] or [$c1if] to indicate which sprite the collision occurred with - inc l - inc l - ld a, [$ff8f] ; a = loop counter - ld de, SpriteCollisionBitTable - add a - add e - ld e, a - jr nc, .noCarry3 - inc d -.noCarry3 - ld a, [de] - or [hl] - ld [hli], a - inc de - ld a, [de] - or [hl] - ld [hl], a - -.next - ld a, [$ff8f] ; a = loop counter - inc a - cp $10 - jp nz, .loop - ret - -; takes delta X or delta Y in a -; b = delta X/Y -; c = 0 if delta X/Y is 0 -; c = 7 if delta X/Y is 1 -; c = 9 if delta X/Y is -1 -SetSpriteCollisionValues: - and a - ld b, 0 - ld c, 0 - jr z, .done - ld c, 9 - cp -1 - jr z, .ok - ld c, 7 - ld a, 0 -.ok - ld b, a -.done - ret - -SpriteCollisionBitTable: - db %00000000,%00000001 - db %00000000,%00000010 - db %00000000,%00000100 - db %00000000,%00001000 - db %00000000,%00010000 - db %00000000,%00100000 - db %00000000,%01000000 - db %00000000,%10000000 - db %00000001,%00000000 - db %00000010,%00000000 - db %00000100,%00000000 - db %00001000,%00000000 - db %00010000,%00000000 - db %00100000,%00000000 - db %01000000,%00000000 - db %10000000,%00000000 - -TestBattle: - ret - -.loop - call GBPalNormal - - ; Don't mess around - ; with obedience. - ld a, %10000000 ; EARTHBADGE - ld [W_OBTAINEDBADGES], a - - ld hl, W_FLAGS_D733 - set 0, [hl] - - ; Reset the party. - ld hl, wPartyCount - xor a - ld [hli], a - dec a - ld [hl], a - - ; Give the player a - ; level 20 Rhydon. - ld a, RHYDON - ld [wcf91], a - ld a, 20 - ld [W_CURENEMYLVL], a - xor a - ld [wcc49], a - ld [W_CURMAP], a - call AddPartyMon - - ; Fight against a - ; level 20 Rhydon. - ld a, RHYDON - ld [W_CUROPPONENT], a - - predef InitOpponent - - ; When the battle ends, - ; do it all again. - ld a, 1 - ld [wUpdateSpritesEnabled], a - ld [H_AUTOBGTRANSFERENABLED], a - jr .loop - -INCLUDE "engine/overworld/item.asm" -INCLUDE "engine/overworld/movement.asm" - -INCLUDE "engine/cable_club.asm" - -LoadTrainerInfoTextBoxTiles: ; 5ae6 (1:5ae6) - ld de, TrainerInfoTextBoxTileGraphics ; $7b98 - ld hl, vChars2 + $760 - ld bc, (BANK(TrainerInfoTextBoxTileGraphics) << 8) +$09 - jp CopyVideoData - -INCLUDE "engine/menu/main_menu.asm" - -INCLUDE "engine/oak_speech.asm" - -SpecialWarpIn: ; 62ce (1:62ce) - call LoadSpecialWarpData - predef LoadTilesetHeader - ld hl,wd732 - bit 2,[hl] ; dungeon warp or fly warp? - res 2,[hl] - jr z,.next -; if dungeon warp or fly warp - ld a,[wDestinationMap] - jr .next2 -.next - bit 1,[hl] - jr z,.next3 - call EmptyFunc -.next3 - ld a,0 -.next2 - ld b,a - ld a,[wd72d] - and a - jr nz,.next4 - ld a,b -.next4 - ld hl,wd732 - bit 4,[hl] ; dungeon warp? - ret nz -; if not dungeon warp - ld [wLastMap],a - ret - -; gets the map ID, tile block map view pointer, tileset, and coordinates -LoadSpecialWarpData: ; 62ff (1:62ff) - ld a, [wd72d] - cp BATTLE_CENTER - jr nz, .notBattleCenter - ld hl, BattleCenterSpec1 - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK ; which gameboy is clocking determines who is on the left and who is on the right - jr z, .copyWarpData - ld hl, BattleCenterSpec2 - jr .copyWarpData -.notBattleCenter - cp TRADE_CENTER - jr nz, .notTradeCenter - ld hl, TradeCenterSpec1 - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .copyWarpData - ld hl, TradeCenterSpec2 - jr .copyWarpData -.notTradeCenter - ld a, [wd732] - bit 1, a - jr nz, .notFirstMap - bit 2, a - jr nz, .notFirstMap - ld hl, FirstMapSpec -.copyWarpData - ld de, W_CURMAP - ld c, $7 -.copyWarpDataLoop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyWarpDataLoop - ld a, [hli] - ld [W_CURMAPTILESET], a - xor a - jr .done -.notFirstMap - ld a, [wLastMap] - ld hl, wd732 - bit 4, [hl] ; used dungeon warp (jumped down hole/waterfall)? - jr nz, .usedDunegonWarp - bit 6, [hl] ; return to last pokemon center (or player's house)? - res 6, [hl] - jr z, .otherDestination -; return to last pokemon center or player's house - ld a, [wLastBlackoutMap] - jr .usedFlyWarp -.usedDunegonWarp - ld hl, wd72d - res 4, [hl] - ld a, [wDungeonWarpDestinationMap] - ld b, a - ld [W_CURMAP], a - ld a, [wWhichDungeonWarp] - ld c, a - ld hl, DungeonWarpList - ld de, $0 - ld a, $6 - ld [wd12f], a -.dungeonWarpListLoop - ld a, [hli] - cp b - jr z, .matchedDungeonWarpDestinationMap - inc hl - jr .nextDungeonWarp -.matchedDungeonWarpDestinationMap - ld a, [hli] - cp c - jr z, .matchedDungeonWarpID -.nextDungeonWarp - ld a, [wd12f] - add e - ld e, a - jr .dungeonWarpListLoop -.matchedDungeonWarpID - ld hl, DungeonWarpData - add hl, de - jr .copyWarpData2 -.otherDestination - ld a, [wDestinationMap] -.usedFlyWarp - ld b, a - ld [W_CURMAP], a - ld hl, FlyWarpDataPtr -.flyWarpDataPtrLoop - ld a, [hli] - inc hl - cp b - jr z, .foundFlyWarpMatch - inc hl - inc hl - jr .flyWarpDataPtrLoop -.foundFlyWarpMatch - ld a, [hli] - ld h, [hl] - ld l, a -.copyWarpData2 - ld de, wCurrentTileBlockMapViewPointer - ld c, $6 -.copyWarpDataLoop2 - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyWarpDataLoop2 - xor a ; OVERWORLD - ld [W_CURMAPTILESET], a -.done - ld [wYOffsetSinceLastSpecialWarp], a - ld [wXOffsetSinceLastSpecialWarp], a - ld a, $ff ; the player's coordinates have already been updated using a special warp, so don't use any of the normal warps - ld [wDestinationWarpID], a - ret - -INCLUDE "data/special_warps.asm" - -; This function appears to never be used. -; It is likely a debugging feature to give the player Tsunekazu Ishihara's -; favorite Pokemon. This is indicated by the overpowered Exeggutor, which -; Ishihara (president of Creatures Inc.) said was his favorite Pokemon in an ABC -; interview on February 8, 2000. -; "Exeggutor is my favorite. That's because I was always using this character -; while I was debugging the program." -; http://www.ign.com/articles/2000/02/09/abc-news-pokamon-chat-transcript - -SetIshiharaTeam: ; 64ca (1:64ca) - ld de, IshiharaTeam -.loop - ld a, [de] - cp $ff - ret z - ld [wcf91], a - inc de - ld a, [de] - ld [W_CURENEMYLVL], a - inc de - call AddPartyMon - jr .loop - -IshiharaTeam: ; 64df (1:64df) - db EXEGGUTOR,90 - db MEW,20 - db JOLTEON,56 - db DUGTRIO,56 - db ARTICUNO,57 - db $FF - -EmptyFunc: ; 64ea (1:64ea) - ret - -INCLUDE "engine/menu/naming_screen.asm" - -INCLUDE "engine/oak_speech2.asm" - -; subtracts the amount the player paid from their money -; sets carry flag if there is enough money and unsets carry flag if not -SubtractAmountPaidFromMoney_: ; 6b21 (1:6b21) - ld de,wPlayerMoney - ld hl,$ff9f ; total price of items - ld c,3 ; length of money in bytes - call StringCmp - ret c - ld de,wPlayerMoney + 2 - ld hl,$ffa1 ; total price of items - ld c,3 ; length of money in bytes - predef SubBCDPredef ; subtract total price from money - ld a,MONEY_BOX - ld [wTextBoxID],a - call DisplayTextBoxID ; redraw money text box - and a - ret - -HandleItemListSwapping: ; 6b44 (1:6b44) - ld a,[wListMenuID] - cp a,ITEMLISTMENU - jp nz,DisplayListMenuIDLoop ; only rearrange item list menus - push hl - ld hl,wList - ld a,[hli] - ld h,[hl] - ld l,a - inc hl ; hl = beginning of list entries - ld a,[wCurrentMenuItem] - ld b,a - ld a,[wListScrollOffset] - add b - add a - ld c,a - ld b,0 - add hl,bc ; hl = address of currently selected item entry - ld a,[hl] - pop hl - inc a - jp z,DisplayListMenuIDLoop ; ignore attempts to swap the Cancel menu item - ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - and a ; has the first item to swap already been chosen? - jr nz,.swapItems -; if not, set the currently selected item as the first item - ld a,[wCurrentMenuItem] - inc a - ld b,a - ld a,[wListScrollOffset] ; index of top (visible) menu item within the list - add b - ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1) - ld c,20 - call DelayFrames - jp DisplayListMenuIDLoop -.swapItems - ld a,[wCurrentMenuItem] - inc a - ld b,a - ld a,[wListScrollOffset] - add b - ld b,a - ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - cp b ; is the currently selected item the same as the first item to swap? - jp z,DisplayListMenuIDLoop ; ignore attempts to swap an item with itself - dec a - ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1) - ld c,20 - call DelayFrames - push hl - push de - ld hl,wList - ld a,[hli] - ld h,[hl] - ld l,a - inc hl ; hl = beginning of list entries - ld d,h - ld e,l ; de = beginning of list entries - ld a,[wCurrentMenuItem] - ld b,a - ld a,[wListScrollOffset] - add b - add a - ld c,a - ld b,0 - add hl,bc ; hl = address of currently selected item entry - ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - add a - add e - ld e,a - jr nc,.noCarry - inc d -.noCarry ; de = address of first item to swap - ld a,[de] - ld b,a - ld a,[hli] - cp b - jr z,.swapSameItemType -.swapDifferentItems - ld [$ff95],a ; [$ff95] = second item ID - ld a,[hld] - ld [$ff96],a ; [$ff96] = second item quantity - ld a,[de] - ld [hli],a ; put first item ID in second item slot - inc de - ld a,[de] - ld [hl],a ; put first item quantity in second item slot - ld a,[$ff96] - ld [de],a ; put second item quantity in first item slot - dec de - ld a,[$ff95] - ld [de],a ; put second item ID in first item slot - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - pop de - pop hl - jp DisplayListMenuIDLoop -.swapSameItemType - inc de - ld a,[hl] - ld b,a - ld a,[de] - add b ; a = sum of both item quantities - cp a,100 ; is the sum too big for one item slot? - jr c,.combineItemSlots -; swap enough items from the first slot to max out the second slot if they can't be combined - sub a,99 - ld [de],a - ld a,99 - ld [hl],a - jr .done -.combineItemSlots - ld [hl],a ; put the sum in the second item slot - ld hl,wList - ld a,[hli] - ld h,[hl] - ld l,a - dec [hl] ; decrease the number of items - ld a,[hl] - ld [wd12a],a ; update number of items variable - cp a,1 - jr nz,.skipSettingMaxMenuItemID - ld [wMaxMenuItem],a ; if the number of items is only one now, update the max menu item ID -.skipSettingMaxMenuItemID - dec de - ld h,d - ld l,e - inc hl - inc hl ; hl = address of item after first item to swap -.moveItemsUpLoop ; erase the first item slot and move up all the following item slots to fill the gap - ld a,[hli] - ld [de],a - inc de - inc a ; reached the $ff terminator? - jr z,.afterMovingItemsUp - ld a,[hli] - ld [de],a - inc de - jr .moveItemsUpLoop -.afterMovingItemsUp - xor a - ld [wListScrollOffset],a - ld [wCurrentMenuItem],a -.done - xor a - ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped - pop de - pop hl - jp DisplayListMenuIDLoop - -INCLUDE "engine/overworld/pokemart.asm" - -INCLUDE "engine/learn_move.asm" - -INCLUDE "engine/overworld/pokecenter.asm" - -SetLastBlackoutMap: -; Set the map to return to when -; blacking out or using Teleport or Dig. -; Safari rest houses don't count. - - push hl - ld hl, SafariZoneRestHouses - ld a, [W_CURMAP] - ld b, a -.loop - ld a, [hli] - cp -1 - jr z, .notresthouse - cp b - jr nz, .loop - jr .done - -.notresthouse - ld a, [wLastMap] - ld [wLastBlackoutMap], a -.done - pop hl - ret - -SafariZoneRestHouses: - db SAFARI_ZONE_REST_HOUSE_2 - db SAFARI_ZONE_REST_HOUSE_3 - db SAFARI_ZONE_REST_HOUSE_4 - db -1 - -; function that performs initialization for DisplayTextID -DisplayTextIDInit: ; 7096 (1:7096) - xor a - ld [wListMenuID],a - ld a,[wAutoTextBoxDrawingControl] - bit 0,a - jr nz,.skipDrawingTextBoxBorder - ld a,[$ff8c] ; text ID (or sprite ID) - and a - jr nz,.notStartMenu -; if text ID is 0 (i.e. the start menu) -; Note that the start menu text border is also drawn in the function directly -; below this, so this seems unnecessary. - ld a,[wd74b] - bit 5,a ; does the player have the pokedex? -; start menu with pokedex - hlCoord 10, 0 - ld b,$0e - ld c,$08 - jr nz,.drawTextBoxBorder -; start menu without pokedex - hlCoord 10, 0 - ld b,$0c - ld c,$08 - jr .drawTextBoxBorder -; if text ID is not 0 (i.e. not the start menu) then do a standard dialogue text box -.notStartMenu - hlCoord 0, 12 - ld b,$04 - ld c,$12 -.drawTextBoxBorder - call TextBoxBorder -.skipDrawingTextBoxBorder - ld hl,wFontLoaded - set 0,[hl] - ld hl,wFlags_0xcd60 - bit 4,[hl] - res 4,[hl] - jr nz,.skipMovingSprites - call UpdateSprites ; move sprites -.skipMovingSprites -; loop to copy C1X9 (direction the sprite is facing) to C2X9 for each sprite -; this is done because when you talk to an NPC, they turn to look your way -; the original direction they were facing must be restored after the dialogue is over - ld hl,wSpriteStateData1 + $19 - ld c,$0f - ld de,$0010 -.spriteFacingDirectionCopyLoop - ld a,[hl] - inc h - ld [hl],a - dec h - add hl,de - dec c - jr nz,.spriteFacingDirectionCopyLoop -; loop to force all the sprites in the middle of animation to stand still -; (so that they don't like they're frozen mid-step during the dialogue) - ld hl,wSpriteStateData1 + 2 - ld de,$0010 - ld c,e -.spriteStandStillLoop - ld a,[hl] - cp a,$ff ; is the sprite visible? - jr z,.nextSprite -; if it is visible - and a,$fc - ld [hl],a -.nextSprite - add hl,de - dec c - jr nz,.spriteStandStillLoop - ld b,$9c ; window background address - call CopyScreenTileBufferToVRAM ; transfer background in WRAM to VRAM - xor a - ld [hWY],a ; put the window on the screen - call LoadFontTilePatterns - ld a,$01 - ld [H_AUTOBGTRANSFERENABLED],a ; enable continuous WRAM to VRAM transfer each V-blank - ret - -; function that displays the start menu -DrawStartMenu: ; 710b (1:710b) - ld a,[wd74b] - bit 5,a ; does the player have the pokedex? -; menu with pokedex - hlCoord 10, 0 - ld b,$0e - ld c,$08 - jr nz,.drawTextBoxBorder -; shorter menu if the player doesn't have the pokedex - hlCoord 10, 0 - ld b,$0c - ld c,$08 -.drawTextBoxBorder - call TextBoxBorder - ld a,%11001011 ; bit mask for down, up, start, B, and A buttons - ld [wMenuWatchedKeys],a - ld a,$02 - ld [wTopMenuItemY],a ; Y position of first menu choice - ld a,$0b - ld [wTopMenuItemX],a ; X position of first menu choice - ld a,[wcc2d] ; remembered menu selection from last time - ld [wCurrentMenuItem],a - ld [wLastMenuItem],a - xor a - ld [wcc37],a - ld hl,wd730 - set 6,[hl] ; no pauses between printing each letter - hlCoord 12, 2 - ld a,[wd74b] - bit 5,a ; does the player have the pokedex? -; case for not having pokdex - ld a,$06 - jr z,.storeMenuItemCount -; case for having pokedex - ld de,StartMenuPokedexText - call PrintStartMenuItem - ld a,$07 -.storeMenuItemCount - ld [wMaxMenuItem],a ; number of menu items - ld de,StartMenuPokemonText - call PrintStartMenuItem - ld de,StartMenuItemText - call PrintStartMenuItem - ld de,wPlayerName ; player's name - call PrintStartMenuItem - ld a,[wd72e] - bit 6,a ; is the player using the link feature? -; case for not using link feature - ld de,StartMenuSaveText - jr z,.printSaveOrResetText -; case for using link feature - ld de,StartMenuResetText -.printSaveOrResetText - call PrintStartMenuItem - ld de,StartMenuOptionText - call PrintStartMenuItem - ld de,StartMenuExitText - call PlaceString - ld hl,wd730 - res 6,[hl] ; turn pauses between printing letters back on - ret - -StartMenuPokedexText: ; 718f (1:718f) - db "POKéDEX@" - -StartMenuPokemonText: ; 7197 (1:7197) - db "POKéMON@" - -StartMenuItemText: ; 719f (1:719f) - db "ITEM@" - -StartMenuSaveText: ; 71a4 (1:71a4) - db "SAVE@" - -StartMenuResetText: ; 71a9 (1:71a9) - db "RESET@" - -StartMenuExitText: ; 71af (1:71af) - db "EXIT@" - -StartMenuOptionText: ; 71b4 (1:71b4) - db "OPTION@" - -PrintStartMenuItem: ; 71bb (1:71bb) - push hl - call PlaceString - pop hl - ld de,$28 - add hl,de - ret - -INCLUDE "engine/overworld/cable_club_npc.asm" - -; function to draw various text boxes -DisplayTextBoxID_: ; 72ea (1:72ea) - ld a,[wTextBoxID] - cp a,TWO_OPTION_MENU - jp z,DisplayTwoOptionMenu - ld c,a - ld hl,TextBoxFunctionTable - ld de,3 - call SearchTextBoxTable - jr c,.functionTableMatch - ld hl,TextBoxCoordTable - ld de,5 - call SearchTextBoxTable - jr c,.coordTableMatch - ld hl,TextBoxTextAndCoordTable - ld de,9 - call SearchTextBoxTable - jr c,.textAndCoordTableMatch -.done - ret -.functionTableMatch - ld a,[hli] - ld h,[hl] - ld l,a ; hl = address of function - ld de,.done - push de - jp [hl] ; jump to the function -.coordTableMatch - call GetTextBoxIDCoords - call GetAddressOfScreenCoords - call TextBoxBorder - ret -.textAndCoordTableMatch - call GetTextBoxIDCoords - push hl - call GetAddressOfScreenCoords - call TextBoxBorder - pop hl - call GetTextBoxIDText - ld a,[wd730] - push af - ld a,[wd730] - set 6,a ; no pauses between printing each letter - ld [wd730],a - call PlaceString - pop af - ld [wd730],a - call UpdateSprites ; move sprites - ret - -; function to search a table terminated with $ff for a byte matching c in increments of de -; sets carry flag if a match is found and clears carry flag if not -SearchTextBoxTable: ; 734c (1:734c) - dec de -.loop - ld a,[hli] - cp a,$ff - jr z,.notFound - cp c - jr z,.found - add hl,de - jr .loop -.found - scf -.notFound - ret - -; function to load coordinates from the TextBoxCoordTable or the TextBoxTextAndCoordTable -; INPUT: -; hl = address of coordinates -; OUTPUT: -; b = height -; c = width -; d = row of upper left corner -; e = column of upper left corner -GetTextBoxIDCoords: ; 735a (1:735a) - ld a,[hli] ; column of upper left corner - ld e,a - ld a,[hli] ; row of upper left corner - ld d,a - ld a,[hli] ; column of lower right corner - sub e - dec a - ld c,a ; c = width - ld a,[hli] ; row of lower right corner - sub d - dec a - ld b,a ; b = height - ret - -; function to load a text address and text coordinates from the TextBoxTextAndCoordTable -GetTextBoxIDText: ; 7367 (1:7367) - ld a,[hli] - ld e,a - ld a,[hli] - ld d,a ; de = address of text - push de ; save text address - ld a,[hli] - ld e,a ; column of upper left corner of text - ld a,[hl] - ld d,a ; row of upper left corner of text - call GetAddressOfScreenCoords - pop de ; restore text address - ret - -; function to point hl to the screen coordinates -; INPUT: -; d = row -; e = column -; OUTPUT: -; hl = address of upper left corner of text box -GetAddressOfScreenCoords: ; 7375 (1:7375) - push bc - ld hl,wTileMap - ld bc,20 -.loop ; loop to add d rows to the base address - ld a,d - and a - jr z,.addedRows - add hl,bc - dec d - jr .loop -.addedRows - pop bc - add hl,de - ret - -; Format: -; 00: text box ID -; 01-02: function address -TextBoxFunctionTable: ; 7387 (1:7387) - dbw MONEY_BOX, DisplayMoneyBox - dbw BUY_SELL_QUIT_MENU, DoBuySellQuitMenu - dbw FIELD_MOVE_MON_MENU, DisplayFieldMoveMonMenu - db $ff ; terminator - -; Format: -; 00: text box ID -; 01: column of upper left corner -; 02: row of upper left corner -; 03: column of lower right corner -; 04: row of lower right corner -TextBoxCoordTable: ; 7391 (1:7391) - db MESSAGE_BOX, 0, 12, 19, 17 - db $03, 0, 0, 19, 14 - db $07, 0, 0, 11, 6 - db LIST_MENU_BOX, 4, 2, 19, 12 - db $10, 7, 0, 19, 17 - db MON_SPRITE_POPUP, 6, 4, 14, 13 - db $ff ; terminator - -; Format: -; 00: text box ID -; 01: column of upper left corner -; 02: row of upper left corner -; 03: column of lower right corner -; 04: row of lower right corner -; 05-06: address of text -; 07: column of beginning of text -; 08: row of beginning of text -; table of window positions and corresponding text [key, start column, start row, end column, end row, text pointer [2 bytes], text column, text row] -TextBoxTextAndCoordTable: ; 73b0 (1:73b0) - db JP_MOCHIMONO_MENU_TEMPLATE - db 0,0,14,17 ; text box coordinates - dw JapaneseMochimonoText - db 3,0 ; text coordinates - - db USE_TOSS_MENU_TEMPLATE - db 13,10,19,14 ; text box coordinates - dw UseTossText - db 15,11 ; text coordinates - - db JP_SAVE_MESSAGE_MENU_TEMPLATE - db 0,0,7,5 ; text box coordinates - dw JapaneseSaveMessageText - db 2,2 ; text coordinates - - db JP_SPEED_OPTIONS_MENU_TEMPLATE - db 0,6,5,10 ; text box coordinates - dw JapaneseSpeedOptionsText - db 2,7 ; text coordinates - - db BATTLE_MENU_TEMPLATE - db 8,12,19,17 ; text box coordinates - dw BattleMenuText - db 10,14 ; text coordinates - - db SAFARI_BATTLE_MENU_TEMPLATE - db 0,12,19,17 ; text box coordinates - dw SafariZoneBattleMenuText - db 2,14 ; text coordinates - - db SWITCH_STATS_CANCEL_MENU_TEMPLATE - db 11,11,19,17 ; text box coordinates - dw SwitchStatsCancelText - db 13,12 ; text coordinates - - db BUY_SELL_QUIT_MENU_TEMPLATE - db 0,0,10,6 ; text box coordinates - dw BuySellQuitText - db 2,1 ; text coordinates - - db MONEY_BOX_TEMPLATE - db 11,0,19,2 ; text box coordinates - dw MoneyText - db 13,0 ; text coordinates - - db JP_AH_MENU_TEMPLATE - db 7,6,11,10 ; text box coordinates - dw JapaneseAhText - db 8,8 ; text coordinates - - db JP_POKEDEX_MENU_TEMPLATE - db 11,8,19,17 ; text box coordinates - dw JapanesePokedexMenu - db 12,10 ; text coordinates - -; note that there is no terminator - -BuySellQuitText: ; 7413 (1:7413) - db "BUY" - next "SELL" - next "QUIT@@" - -UseTossText: ; 7422 (1:7422) - db "USE" - next "TOSS@" - -JapaneseSaveMessageText: ; 742b (1:742b) - db "きろく" - next "メッセージ@" - -JapaneseSpeedOptionsText: ; 7435 (1:7435) - db "はやい" - next "おそい@" - -MoneyText: ; 743d (1:743d) - db "MONEY@" - -JapaneseMochimonoText: ; 7443 (1:7443) - db "もちもの@" - -JapaneseMainMenuText: ; 7448 (1:7448) - db "つづきから" - next "さいしょから@" - -BattleMenuText: ; 7455 (1:7455) - db "FIGHT ",$E1,$E2 - next "ITEM RUN@" - -SafariZoneBattleMenuText: ; 7468 (1:7468) - db "BALL× BAIT" - next "THROW ROCK RUN@" - -SwitchStatsCancelText: ; 7489 (1:7489) - db "SWITCH" - next "STATS" - next "CANCEL@" - -JapaneseAhText: ; 749d (1:749d) - db "アッ!@" - -JapanesePokedexMenu: ; 74a1 (1:74a1) - db "データをみる" - next "なきごえ" - next "ぶんぷをみる" - next "キャンセル@" - -DisplayMoneyBox: ; 74ba (1:74ba) - ld hl, wd730 - set 6, [hl] - ld a, MONEY_BOX_TEMPLATE - ld [wTextBoxID], a - call DisplayTextBoxID - hlCoord 13, 1 - ld b, $1 - ld c, $6 - call ClearScreenArea - hlCoord 12, 1 - ld de, wPlayerMoney - ld c, $a3 - call PrintBCDNumber - ld hl, wd730 - res 6, [hl] - ret - -CurrencyString: ; 74e2 (1:74e2) - db " ¥@" - -DoBuySellQuitMenu: ; 74ea (1:74ea) - ld a, [wd730] - set 6, a ; no printing delay - ld [wd730], a - xor a - ld [wd12d], a - ld a, BUY_SELL_QUIT_MENU_TEMPLATE - ld [wTextBoxID], a - call DisplayTextBoxID - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, $2 - ld [wMaxMenuItem], a - ld a, $1 - ld [wTopMenuItemY], a - ld a, $1 - ld [wTopMenuItemX], a - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [wcc37], a - ld a, [wd730] - res 6, a ; turn on the printing delay - ld [wd730], a - call HandleMenuInput - call PlaceUnfilledArrowMenuCursor - bit 0, a ; was A pressed? - jr nz, .pressedA - bit 1, a ; was B pressed? (always true since only A/B are watched) - jr z, .pressedA - ld a, $2 - ld [wd12e], a - jr .quit -.pressedA - ld a, $1 - ld [wd12e], a - ld a, [wCurrentMenuItem] - ld [wd12d], a - ld b, a - ld a, [wMaxMenuItem] - cp b - jr z, .quit - ret -.quit - ld a, $2 - ld [wd12e], a - ld a, [wCurrentMenuItem] - ld [wd12d], a - scf - ret - -; displays a menu with two options to choose from -; b = Y of upper left corner of text region -; c = X of upper left corner of text region -; hl = address where the text box border should be drawn -DisplayTwoOptionMenu: ; 7559 (1:7559) - push hl - ld a, [wd730] - set 6, a ; no printing delay - ld [wd730], a - xor a - ld [wd12d], a - ld [wd12e], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, $1 - ld [wMaxMenuItem], a - ld a, b - ld [wTopMenuItemY], a - ld a, c - ld [wTopMenuItemX], a - xor a - ld [wLastMenuItem], a - ld [wcc37], a - push hl - ld hl, wTwoOptionMenuID - bit 7, [hl] ; select second menu item by default? - res 7, [hl] - jr z, .storeCurrentMenuItem - inc a -.storeCurrentMenuItem - ld [wCurrentMenuItem], a - pop hl - push hl - push hl - call TwoOptionMenu_SaveScreenTiles - ld a, [wTwoOptionMenuID] - ld hl, TwoOptionMenuStrings - ld e, a - ld d, $0 - ld a, $5 -.menuStringLoop - add hl, de - dec a - jr nz, .menuStringLoop - ld a, [hli] - ld c, a - ld a, [hli] - ld b, a - ld e, l - ld d, h - pop hl - push de - ld a, [wTwoOptionMenuID] - cp TRADE_CANCEL_MENU - jr nz, .notTradeCancelMenu - call CableClub_TextBoxBorder - jr .afterTextBoxBorder -.notTradeCancelMenu - call TextBoxBorder -.afterTextBoxBorder - call UpdateSprites - pop hl - ld a, [hli] - and a ; put blank line before first menu item? - ld bc, 20 + 2 - jr z, .noBlankLine - ld bc, 2 * 20 + 2 -.noBlankLine - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - pop hl - add hl, bc - call PlaceString - ld hl, wd730 - res 6, [hl] ; turn on the printing delay - ld a, [wTwoOptionMenuID] - cp NO_YES_MENU - jr nz, .notNoYesMenu -; No/Yes menu -; this menu type ignores the B button -; it only seems to be used when confirming the deletion of a save file - xor a - ld [wTwoOptionMenuID], a - ld a, [wFlags_0xcd60] - push af - push hl - ld hl, wFlags_0xcd60 - bit 5, [hl] - set 5, [hl] ; don't play sound when A or B is pressed in menu - pop hl -.noYesMenuInputLoop - call HandleMenuInput - bit 1, a ; A button pressed? - jr nz, .noYesMenuInputLoop ; try again if A was not pressed - pop af - pop hl - ld [wFlags_0xcd60], a - ld a, (SFX_02_40 - SFX_Headers_02) / 3 - call PlaySound - jr .pressedAButton -.notNoYesMenu - xor a - ld [wTwoOptionMenuID], a - call HandleMenuInput - pop hl - bit 1, a ; A button pressed? - jr nz, .choseSecondMenuItem ; automatically choose the second option if B is pressed -.pressedAButton - ld a, [wCurrentMenuItem] - ld [wd12d], a - and a - jr nz, .choseSecondMenuItem -; chose first menu item - ld a, $1 - ld [wd12e], a - ld c, 15 - call DelayFrames - call TwoOptionMenu_RestoreScreenTiles - and a - ret -.choseSecondMenuItem - ld a, $1 - ld [wCurrentMenuItem], a - ld [wd12d], a - ld a, $2 - ld [wd12e], a - ld c, 15 - call DelayFrames - call TwoOptionMenu_RestoreScreenTiles - scf - ret - -; Some of the wider/taller two option menus will not have the screen areas -; they cover be fully saved/restored by the two functions below. -; The bottom and right edges of the menu may remain after the function returns. - -TwoOptionMenu_SaveScreenTiles: ; 763e (1:763e) - ld de, wHPBarMaxHP - ld bc, $506 -.asm_7644 - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .asm_7644 - push bc - ld bc, 14 - add hl, bc - pop bc - ld c, $6 - dec b - jr nz, .asm_7644 - ret - -TwoOptionMenu_RestoreScreenTiles: ; 7656 (1:7656) - ld de, wHPBarMaxHP - ld bc, $506 -.asm_765c - ld a, [de] - inc de - ld [hli], a - dec c - jr nz, .asm_765c - push bc - ld bc, $e - add hl, bc - pop bc - ld c, $6 - dec b - jr nz, .asm_765c - call UpdateSprites - ret - -; Format: -; 00: byte width -; 01: byte height -; 02: byte put blank line before first menu item -; 03: word text pointer -TwoOptionMenuStrings: ; 7671 (1:7671) - db 4,3,0 - dw .YesNoMenu - db 6,3,0 - dw .NorthWestMenu - db 6,3,0 - dw .SouthEastMenu - db 6,3,0 - dw .YesNoMenu - db 6,3,0 - dw .NorthEastMenu - db 7,3,0 - dw .TradeCancelMenu - db 7,4,1 - dw .HealCancelMenu - db 4,3,0 - dw .NoYesMenu - -.NoYesMenu ; 7699 (1:3699) - db "NO",$4E,"YES@" -.YesNoMenu ; 76a0 (1:36a0) - db "YES",$4E,"NO@" -.NorthWestMenu ; 76a7 (1:36a7) - db "NORTH",$4E,"WEST@" -.SouthEastMenu ; 76b2 (1:36b2) - db "SOUTH",$4E,"EAST@" -.NorthEastMenu ; 76bd (1:36bd) - db "NORTH",$4E,"EAST@" -.TradeCancelMenu ; 76c8 (1:36c8) - db "TRADE",$4E,"CANCEL@" -.HealCancelMenu ; 76d5 (1:36d5) - db "HEAL",$4E,"CANCEL@" - -DisplayFieldMoveMonMenu: ; 76e1 (1:36e1) - xor a - ld hl, wWhichTrade - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hl], $c - call GetMonFieldMoves - ld a, [wTrainerScreenX] - and a - jr nz, .asm_770f - hlCoord 11, 11 - ld b, $5 - ld c, $7 - call TextBoxBorder - call UpdateSprites - ld a, $c - ld [$fff7], a - hlCoord 13, 12 - ld de, PokemonMenuEntries - jp PlaceString -.asm_770f - push af - hlCoord 0, 11 - ld a, [wcd42] - dec a - ld e, a - ld d, $0 - add hl, de - ld b, $5 - ld a, $12 - sub e - ld c, a - pop af - ld de, $ffd8 -.asm_7725 - add hl, de - inc b - inc b - dec a - jr nz, .asm_7725 - ld de, $ffec - add hl, de - inc b - call TextBoxBorder - call UpdateSprites - hlCoord 0, 12 - ld a, [wcd42] - inc a - ld e, a - ld d, $0 - add hl, de - ld de, $ffd8 - ld a, [wTrainerScreenX] -.asm_7747 - add hl, de - dec a - jr nz, .asm_7747 - xor a - ld [wTrainerScreenX], a - ld de, wWhichTrade -.asm_7752 - push hl - ld hl, FieldMoveNames - ld a, [de] - and a - jr z, .asm_7776 - inc de - ld b, a -.asm_775c - dec b - jr z, .asm_7766 -.asm_775f - ld a, [hli] - cp $50 - jr nz, .asm_775f - jr .asm_775c -.asm_7766 - ld b, h - ld c, l - pop hl - push de - ld d, b - ld e, c - call PlaceString - ld bc, $28 - add hl, bc - pop de - jr .asm_7752 -.asm_7776 - pop hl - ld a, [wcd42] - ld [$fff7], a - hlCoord 0, 12 - ld a, [wcd42] - inc a - ld e, a - ld d, $0 - add hl, de - ld de, PokemonMenuEntries - jp PlaceString - -FieldMoveNames: ; 778d (1:778d) - db "CUT@" - db "FLY@" - db "@" - db "SURF@" - db "STRENGTH@" - db "FLASH@" - db "DIG@" - db "TELEPORT@" - db "SOFTBOILED@" - -PokemonMenuEntries: ; 77c2 (1:77c2) - db "STATS" - next "SWITCH" - next "CANCEL@" - -GetMonFieldMoves: ; 77d6 (1:77d6) - ld a, [wWhichPokemon] - ld hl, wPartyMon1Moves - ld bc, $2c - call AddNTimes - ld d, h - ld e, l - ld c, $5 - ld hl, wWhichTrade -.asm_77e9 - push hl -.asm_77ea - dec c - jr z, .asm_7821 - ld a, [de] ; de is RAM address of move - and a - jr z, .asm_7821 - ld b, a - inc de ; go to next move - ld hl, FieldMoveDisplayData -.asm_77f6 - ld a, [hli] - cp $ff - jr z, .asm_77ea - cp b - jr z, .asm_7802 - inc hl - inc hl - jr .asm_77f6 -.asm_7802 - ld a, b - ld [wcd43], a - ld a, [hli] - ld b, [hl] - pop hl - ld [hli], a - ld a, [wTrainerScreenX] - inc a - ld [wTrainerScreenX], a - ld a, [wcd42] - cp b - jr c, .asm_781b - ld a, b - ld [wcd42], a -.asm_781b - ld a, [wcd43] - ld b, a - jr .asm_77e9 -.asm_7821 - pop hl - ret - -; Format: [Move id], [list priority], [leftmost tile] -; Move id = id of move -; List priority = lower number means higher priority when field moves are displayed -; these priorities must be unique -; Leftmost tile = -1 + tile column in which the first letter of the move's name should be displayed -; "SOFTBOILED" is $08 because it has 4 more letters than "SURF", for example, whose value is $0C -FieldMoveDisplayData: ; 7823 (1:7823) - db CUT, $01, $0C - db FLY, $02, $0C - db $B4, $03, $0C ; unused field move - db SURF, $04, $0C - db STRENGTH, $05, $0A - db FLASH, $06, $0C - db DIG, $07, $0C - db TELEPORT, $08, $0A - db SOFTBOILED, $09, $08 - db $ff ; list terminator - - -INCLUDE "engine/battle/moveEffects/drain_hp_effect.asm" - -INCLUDE "engine/menu/players_pc.asm" - -_RemovePokemon: ; 7b68 (1:7b68) - ld hl, wPartyCount ; wPartyCount - ld a, [wcf95] - and a - jr z, .asm_7b74 - ld hl, W_NUMINBOX ; wda80 -.asm_7b74 - ld a, [hl] - dec a - ld [hli], a - ld a, [wWhichPokemon] ; wWhichPokemon - ld c, a - ld b, $0 - add hl, bc - ld e, l - ld d, h - inc de -.asm_7b81 - ld a, [de] - inc de - ld [hli], a - inc a - jr nz, .asm_7b81 - ld hl, wPartyMonOT ; wd273 - ld d, $5 - ld a, [wcf95] - and a - jr z, .asm_7b97 - ld hl, wBoxMonOT - ld d, $13 -.asm_7b97 - ld a, [wWhichPokemon] ; wWhichPokemon - call SkipFixedLengthTextEntries - ld a, [wWhichPokemon] ; wWhichPokemon - cp d - jr nz, .asm_7ba6 - ld [hl], $ff - ret -.asm_7ba6 - ld d, h - ld e, l - ld bc, $b - add hl, bc - ld bc, wPartyMonNicks ; wPartyMonNicks - ld a, [wcf95] - and a - jr z, .asm_7bb8 - ld bc, wBoxMonNicks -.asm_7bb8 - call CopyDataUntil - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wcf95] - and a - jr z, .asm_7bcd - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 -.asm_7bcd - ld a, [wWhichPokemon] ; wWhichPokemon - call AddNTimes - ld d, h - ld e, l - ld a, [wcf95] - and a - jr z, .asm_7be4 - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld bc, wBoxMonOT - jr .asm_7beb -.asm_7be4 - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - ld bc, wPartyMonOT ; wd273 -.asm_7beb - call CopyDataUntil - ld hl, wPartyMonNicks ; wPartyMonNicks - ld a, [wcf95] - and a - jr z, .asm_7bfa - ld hl, wBoxMonNicks -.asm_7bfa - ld bc, $b - ld a, [wWhichPokemon] ; wWhichPokemon - call AddNTimes - ld d, h - ld e, l - ld bc, $b - add hl, bc - ld bc, wPokedexOwned ; wPokedexOwned - ld a, [wcf95] - and a - jr z, .asm_7c15 - ld bc, wBoxMonNicksEnd -.asm_7c15 - jp CopyDataUntil - -Func_7c18: ; 7c18 (1:7c18) - ld hl, wd730 - set 6, [hl] - predef ShowPokedexData - ld hl, wd730 - res 6, [hl] - call ReloadMapData - ld c, $a - call DelayFrames - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld b, $1 - ld hl, wPokedexSeen - predef FlagActionPredef - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ret - - -SECTION "bank3",ROMX,BANK[$3] - -INCLUDE "engine/joypad.asm" - -INCLUDE "data/map_songs.asm" - -INCLUDE "data/map_header_banks.asm" - -ClearVariablesAfterLoadingMapData: ; c335 (3:4335) - ld a, $90 - ld [hWY], a - ld [rWY], a - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [wStepCounter], a - ld [W_LONEATTACKNO], a ; W_GYMLEADERNO - ld [hJoyPressed], a - ld [hJoyReleased], a - ld [hJoyHeld], a - ld [wcd6a], a - ld [wd5a3], a - ld hl, wCardKeyDoorY - ld [hli], a - ld [hl], a - ld hl, wWhichTrade - ld bc, $1e - call FillMemory - ret - -; only used for setting bit 2 of wd736 upon entering a new map -IsPlayerStandingOnWarp: ; c35f (3:435f) - ld a, [wNumberOfWarps] - and a - ret z - ld c, a - ld hl, wWarpEntries -.loop - ld a, [W_YCOORD] - cp [hl] - jr nz, .nextWarp1 - inc hl - ld a, [W_XCOORD] - cp [hl] - jr nz, .nextWarp2 - inc hl - ld a, [hli] ; target warp - ld [wDestinationWarpID], a - ld a, [hl] ; target map - ld [$ff8b], a - ld hl, wd736 - set 2, [hl] ; standing on warp flag - ret -.nextWarp1 - inc hl -.nextWarp2 - inc hl - inc hl - inc hl - dec c - jr nz, .loop - ret - -CheckForceBikeOrSurf: ; c38b (3:438b) - ld hl, wd732 - bit 5, [hl] - ret nz - ld hl, ForcedBikeOrSurfMaps - ld a, [W_YCOORD] - ld b, a - ld a, [W_XCOORD] - ld c, a - ld a, [W_CURMAP] - ld d, a -.loop - ld a, [hli] - cp $ff - ret z ;if we reach FF then it's not part of the list - cp d ;compare to current map - jr nz, .incorrectMap - ld a, [hli] - cp b ;compare y-coord - jr nz, .incorrectY - ld a, [hli] - cp c ;compare x-coord - jr nz, .loop ; incorrect x-coord, check next item - ld a, [W_CURMAP] - cp SEAFOAM_ISLANDS_4 - ld a, $2 - ld [W_SEAFOAMISLANDS4CURSCRIPT], a - jr z, .forceSurfing - ld a, [W_CURMAP] - cp SEAFOAM_ISLANDS_5 - ld a, $2 - ld [W_SEAFOAMISLANDS5CURSCRIPT], a - jr z, .forceSurfing - ;force bike riding - ld hl, wd732 - set 5, [hl] - ld a, $1 - ld [wWalkBikeSurfState], a - ld [wWalkBikeSurfStateCopy], a - jp ForceBikeOrSurf -.incorrectMap - inc hl -.incorrectY - inc hl - jr .loop -.forceSurfing - ld a, $2 - ld [wWalkBikeSurfState], a - ld [wWalkBikeSurfStateCopy], a - jp ForceBikeOrSurf - -INCLUDE "data/force_bike_surf.asm" - -IsPlayerFacingEdgeOfMap: ; c3ff (3:43ff) - push hl - push de - push bc - ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction - srl a - ld c, a - ld b, $0 - ld hl, .functionPointerTable - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [W_YCOORD] - ld b, a - ld a, [W_XCOORD] - ld c, a - ld de, .asm_c41e - push de - jp [hl] -.asm_c41e - pop bc - pop de - pop hl - ret - -.functionPointerTable - dw .facingDown - dw .facingUp - dw .facingLeft - dw .facingRight - -.facingDown - ld a, [W_CURMAPHEIGHT] - add a - dec a - cp b - jr z, .setCarry - jr .resetCarry - -.facingUp - ld a, b - and a - jr z, .setCarry - jr .resetCarry - -.facingLeft - ld a, c - and a - jr z, .setCarry - jr .resetCarry - -.facingRight - ld a, [W_CURMAPWIDTH] - add a - dec a - cp c - jr z, .setCarry - jr .resetCarry -.resetCarry - and a - ret -.setCarry - scf - ret - -IsWarpTileInFrontOfPlayer: ; c44e (3:444e) - push hl - push de - push bc - call _GetTileAndCoordsInFrontOfPlayer - ld a, [W_CURMAP] - cp SS_ANNE_5 - jr z, .ssAnne5 - ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction - srl a - ld c, a - ld b, 0 - ld hl, .warpTileListPointers - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [wTileInFrontOfPlayer] - ld de, $1 - call IsInArray -.done - pop bc - pop de - pop hl - ret - -.warpTileListPointers: ; c477 (3:4477) - dw .facingDownWarpTiles - dw .facingUpWarpTiles - dw .facingLeftWarpTiles - dw .facingRightWarpTiles - -.facingDownWarpTiles - db $01,$12,$17,$3D,$04,$18,$33,$FF - -.facingUpWarpTiles - db $01,$5C,$FF - -.facingLeftWarpTiles - db $1A,$4B,$FF - -.facingRightWarpTiles - db $0F,$4E,$FF - -.ssAnne5 - ld a, [wTileInFrontOfPlayer] - cp $15 - jr nz, .notSSAnne5Warp - scf - jr .done -.notSSAnne5Warp - and a - jr .done - -IsPlayerStandingOnDoorTileOrWarpTile: ; c49d (3:449d) - push hl - push de - push bc - callba IsPlayerStandingOnDoorTile - jr c, .done - ld a, [W_CURMAPTILESET] - add a - ld c, a - ld b, $0 - ld hl, WarpTileIDPointers - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld de, $1 - aCoord 8, 9 - call IsInArray - jr nc, .done - ld hl, wd736 - res 2, [hl] -.done - pop bc - pop de - pop hl - ret - -INCLUDE "data/warp_tile_ids.asm" - -PrintSafariZoneSteps: ; c52f (3:452f) - ld a, [W_CURMAP] ; W_CURMAP - cp SAFARI_ZONE_EAST - ret c - cp UNKNOWN_DUNGEON_2 - ret nc - ld hl, wTileMap - ld b, $3 - ld c, $7 - call TextBoxBorder - hlCoord 1, 1 - ld de, wSafariSteps ; wd70d - ld bc, $203 - call PrintNumber - hlCoord 4, 1 - ld de, SafariSteps ; $4579 - call PlaceString - hlCoord 1, 3 - ld de, SafariBallText - call PlaceString - ld a, [W_NUMSAFARIBALLS] ; W_NUMSAFARIBALLS - cp $a - jr nc, .asm_c56d - hlCoord 5, 3 - ld a, $7f - ld [hl], a -.asm_c56d - hlCoord 6, 3 - ld de, W_NUMSAFARIBALLS ; W_NUMSAFARIBALLS - ld bc, $102 - jp PrintNumber - -SafariSteps: ; c579 (3:4579) - db "/500@" - -SafariBallText: ; c57e (3:457e) - db "BALL×× @" - -GetTileAndCoordsInFrontOfPlayer: ; c586 (3:4586) - call GetPredefRegisters - -_GetTileAndCoordsInFrontOfPlayer: ; c589 (3:4589) - ld a, [W_YCOORD] - ld d, a - ld a, [W_XCOORD] - ld e, a - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction - and a - jr nz, .notFacingDown -; facing down - aCoord 8, 11 - inc d - jr .storeTile -.notFacingDown - cp SPRITE_FACING_UP - jr nz, .notFacingUp -; facing up - aCoord 8, 7 - dec d - jr .storeTile -.notFacingUp - cp SPRITE_FACING_LEFT - jr nz, .notFacingLeft -; facing left - aCoord 6, 9 - dec e - jr .storeTile -.notFacingLeft - cp SPRITE_FACING_RIGHT - jr nz, .storeTile -; facing right - aCoord 10, 9 - inc e -.storeTile - ld c, a - ld [wTileInFrontOfPlayer], a - ret - -GetTileTwoStepsInFrontOfPlayer: ; c5be (3:45be) - xor a - ld [$ffdb], a - ld hl, W_YCOORD - ld a, [hli] - ld d, a - ld e, [hl] - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction - and a - jr nz, .notFacingDown -; facing down - ld hl, $ffdb - set 0, [hl] - aCoord 8, 13 - inc d - jr .storeTile -.notFacingDown - cp SPRITE_FACING_UP - jr nz, .notFacingUp -; facing up - ld hl, $ffdb - set 1, [hl] - aCoord 8, 5 - dec d - jr .storeTile -.notFacingUp - cp SPRITE_FACING_LEFT - jr nz, .notFacingLeft -; facing left - ld hl, $ffdb - set 2, [hl] - aCoord 4, 9 - dec e - jr .storeTile -.notFacingLeft - cp SPRITE_FACING_RIGHT - jr nz, .storeTile -; facing right - ld hl, $ffdb - set 3, [hl] - aCoord 12, 9 - inc e -.storeTile - ld c, a - ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a - ld [wTileInFrontOfPlayer], a - ret - -CheckForCollisionWhenPushingBoulder: ; c60b (3:460b) - call GetTileTwoStepsInFrontOfPlayer - ld hl, W_TILESETCOLLISIONPTR - ld a, [hli] - ld h, [hl] - ld l, a -.loop - ld a, [hli] - cp $ff - jr z, .done ; if the tile two steps ahead is not passable - cp c - jr nz, .loop - ld hl, TilePairCollisionsLand - call CheckForTilePairCollisions2 - ld a, $ff - jr c, .done ; if there is an elevation difference between the current tile and the one two steps ahead - ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult] - cp $15 ; stairs tile - ld a, $ff - jr z, .done ; if the tile two steps ahead is stairs - call CheckForBoulderCollisionWithSprites -.done - ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a - ret - -; sets a to $ff if there is a collision and $00 if there is no collision -CheckForBoulderCollisionWithSprites: ; c636 (3:4636) - ld a, [wBoulderSpriteIndex] - dec a - swap a - ld d, 0 - ld e, a - ld hl, wSpriteStateData2 + $14 - add hl, de - ld a, [hli] ; map Y position - ld [$ffdc], a - ld a, [hl] ; map X position - ld [$ffdd], a - ld a, [W_NUMSPRITES] - ld c, a - ld de, $f - ld hl, wSpriteStateData2 + $14 - ld a, [$ffdb] - and $3 ; facing up or down? - jr z, .pushingHorizontallyLoop -.pushingVerticallyLoop - inc hl - ld a, [$ffdd] - cp [hl] - jr nz, .nextSprite1 ; if X coordinates don't match - dec hl - ld a, [hli] - ld b, a - ld a, [$ffdb] - rrca - jr c, .pushingDown -; pushing up - ld a, [$ffdc] - dec a - jr .compareYCoords -.pushingDown - ld a, [$ffdc] - inc a -.compareYCoords - cp b - jr z, .failure -.nextSprite1 - dec c - jr z, .success - add hl, de - jr .pushingVerticallyLoop -.pushingHorizontallyLoop - ld a, [hli] - ld b, a - ld a, [$ffdc] - cp b - jr nz, .nextSprite2 - ld b, [hl] - ld a, [$ffdb] - bit 2, a - jr nz, .pushingLeft -; pushing right - ld a, [$ffdd] - inc a - jr .compareXCoords -.pushingLeft - ld a, [$ffdd] - dec a -.compareXCoords - cp b - jr z, .failure -.nextSprite2 - dec c - jr z, .success - add hl, de - jr .pushingHorizontallyLoop -.failure - ld a, $ff - ret -.success - xor a - ret - -ApplyOutOfBattlePoisonDamage: ; c69c (3:469c) - ld a, [wd730] - add a - jp c, .noBlackOut ; no black out if joypad states are being simulated - ld a, [wPartyCount] - and a - jp z, .noBlackOut - call IncrementDayCareMonExp - ld a, [wStepCounter] - and $3 ; is the counter a multiple of 4? - jp nz, .noBlackOut ; only apply poison damage every fourth step - ld [wWhichPokemon], a - ld hl, wPartyMon1Status - ld de, wPartySpecies -.applyDamageLoop - ld a, [hl] - and (1 << PSN) - jr z, .nextMon2 ; not poisoned - dec hl - dec hl - ld a, [hld] - ld b, a - ld a, [hli] - or b - jr z, .nextMon ; already fainted -; subtract 1 from HP - ld a, [hl] - dec a - ld [hld], a - inc a - jr nz, .noBorrow -; borrow 1 from upper byte of HP - dec [hl] - inc hl - jr .nextMon -.noBorrow - ld a, [hli] - or [hl] - jr nz, .nextMon ; didn't faint from damage -; the mon fainted from the damage - push hl - inc hl - inc hl - ld [hl], a - ld a, [de] - ld [wd11e], a - push de - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - xor a - ld [wJoyIgnore], a - call EnableAutoTextBoxDrawing - ld a, $d0 - ld [$ff8c], a - call DisplayTextID - pop de - pop hl -.nextMon - inc hl - inc hl -.nextMon2 - inc de - ld a, [de] - inc a - jr z, .applyDamageLoopDone - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - push hl - ld hl, wWhichPokemon - inc [hl] - pop hl - jr .applyDamageLoop -.applyDamageLoopDone - ld hl, wPartyMon1Status - ld a, [wPartyCount] - ld d, a - ld e, 0 -.countPoisonedLoop - ld a, [hl] - and (1 << PSN) - or e - ld e, a - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - dec d - jr nz, .countPoisonedLoop - ld a, e - and a ; are any party members poisoned? - jr z, .skipPoisonEffectAndSound - ld b, $2 - predef ChangeBGPalColor0_4Frames ; change BG white to dark grey for 4 frames - ld a, (SFX_02_43 - SFX_Headers_02) / 3 - call PlaySound -.skipPoisonEffectAndSound - predef AnyPartyAlive - ld a, d - and a - jr nz, .noBlackOut - call EnableAutoTextBoxDrawing - ld a, $d1 - ld [$ff8c], a - call DisplayTextID - ld hl, wd72e - set 5, [hl] - ld a, $ff - jr .done -.noBlackOut - xor a -.done - ld [wd12d], a - ret - -LoadTilesetHeader: ; c754 (3:4754) - call GetPredefRegisters - push hl - ld d, 0 - ld a, [W_CURMAPTILESET] - add a - add a - ld b, a - add a - add b ; a = tileset * 12 - jr nc, .noCarry - inc d -.noCarry - ld e, a - ld hl, Tilesets - add hl, de - ld de, W_TILESETBANK - ld c, $b -.copyTilesetHeaderLoop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyTilesetHeaderLoop - ld a, [hl] - ld [hTilesetType], a - xor a - ld [$ffd8], a - pop hl - ld a, [W_CURMAPTILESET] - push hl - push de - ld hl, DungeonTilesets - ld de, $1 - call IsInArray - pop de - pop hl - jr c, .asm_c797 - ld a, [W_CURMAPTILESET] - ld b, a - ld a, [$ff8b] - cp b - jr z, .done -.asm_c797 - ld a, [wDestinationWarpID] - cp $ff - jr z, .done - call LoadDestinationWarpPosition - ld a, [W_YCOORD] - and $1 - ld [W_YBLOCKCOORD], a - ld a, [W_XCOORD] - and $1 - ld [W_XBLOCKCOORD], a -.done - ret - -INCLUDE "data/dungeon_tilesets.asm" - -INCLUDE "data/tileset_headers.asm" - -IncrementDayCareMonExp: ; c8de (3:48de) - ld a, [W_DAYCARE_IN_USE] - and a - ret z - ld hl, wDayCareMonExp + 2 - inc [hl] - ret nz - dec hl - inc [hl] - ret nz - dec hl - inc [hl] - ld a, [hl] - cp $50 - ret c - ld a, $50 - ld [hl], a - ret - -INCLUDE "data/hide_show_data.asm" - -PrintStrengthTxt: ; cd99 (3:4d99) - ld hl, wd728 - set 0, [hl] - ld hl, UsedStrengthText - call PrintText - ld hl, CanMoveBouldersText - jp PrintText - -UsedStrengthText: ; cdaa (3:4daa) - TX_FAR _UsedStrengthText - db $08 ; asm - ld a, [wcf91] - call PlayCry - call Delay3 - jp TextScriptEnd - -CanMoveBouldersText: ; cdbb (3:4dbb) - TX_FAR _CanMoveBouldersText - db "@" - -CheckForForcedBikeSurf: ; cdc0 (3:4dc0) - ld hl, wd728 - set 1, [hl] - ld a, [wd732] - bit 5, a - jr nz, .asm_cdec - ld a, [W_CURMAP] ; W_CURMAP - cp SEAFOAM_ISLANDS_5 - ret nz - ld a, [wd881] - and $3 - cp $3 - ret z - ld hl, CoordsData_cdf7 ; $4df7 - call ArePlayerCoordsInArray - ret nc - ld hl, wd728 - res 1, [hl] - ld hl, CurrentTooFastText - jp PrintText -.asm_cdec - ld hl, wd728 - res 1, [hl] - ld hl, CyclingIsFunText - jp PrintText - -CoordsData_cdf7: ; cdf7 (3:4df7) - db $0B,$07,$FF - -CurrentTooFastText: ; cdfa (3:4dfa) - TX_FAR _CurrentTooFastText - db "@" - -CyclingIsFunText: ; cdff (3:4dff) - TX_FAR _CyclingIsFunText - db "@" - -; function to add an item (in varying quantities) to the player's bag or PC box -; INPUT: -; hl = address of inventory (either wNumBagItems or wNumBoxItems) -; [wcf91] = item ID -; [wcf96] = item quantity -; sets carry flag if successful, unsets carry flag if unsuccessful -AddItemToInventory_: ; ce04 (3:4e04) - ld a,[wcf96] ; a = item quantity - push af - push bc - push de - push hl - push hl - ld d,50 ; PC box can hold 50 items - ld a,wNumBagItems & $FF - cp l - jr nz,.checkIfInventoryFull - ld a,wNumBagItems >> 8 - cp h - jr nz,.checkIfInventoryFull -; if the destination is the bag - ld d,20 ; bag can hold 20 items -.checkIfInventoryFull - ld a,[hl] - sub d - ld d,a - ld a,[hli] - and a - jr z,.addNewItem -.loop - ld a,[hli] - ld b,a ; b = ID of current item in table - ld a,[wcf91] ; a = ID of item being added - cp b ; does the current item in the table match the item being added? - jp z,.increaseItemQuantity ; if so, increase the item's quantity - inc hl - ld a,[hl] - cp a,$ff ; is it the end of the table? - jr nz,.loop -.addNewItem ; add an item not yet in the inventory - pop hl - ld a,d - and a ; is there room for a new item slot? - jr z,.done -; if there is room - inc [hl] ; increment the number of items in the inventory - ld a,[hl] ; the number of items will be the index of the new item - add a - dec a - ld c,a - ld b,0 - add hl,bc ; hl = address to store the item - ld a,[wcf91] - ld [hli],a ; store item ID - ld a,[wcf96] - ld [hli],a ; store item quantity - ld [hl],$ff ; store terminator - jp .success -.increaseItemQuantity ; increase the quantity of an item already in the inventory - ld a,[wcf96] - ld b,a ; b = quantity to add - ld a,[hl] ; a = existing item quantity - add b ; a = new item quantity - cp a,100 - jp c,.storeNewQuantity ; if the new quantity is less than 100, store it -; if the new quantity is greater than or equal to 100, -; try to max out the current slot and add the rest in a new slot - sub a,99 - ld [wcf96],a ; a = amount left over (to put in the new slot) - ld a,d - and a ; is there room for a new item slot? - jr z,.increaseItemQuantityFailed -; if so, store 99 in the current slot and store the rest in a new slot - ld a,99 - ld [hli],a - jp .loop -.increaseItemQuantityFailed - pop hl - and a - jr .done -.storeNewQuantity - ld [hl],a - pop hl -.success - scf -.done - pop hl - pop de - pop bc - pop bc - ld a,b - ld [wcf96],a ; restore the initial value from when the function was called - ret - -; function to remove an item (in varying quantities) from the player's bag or PC box -; INPUT: -; hl = address of inventory (either wNumBagItems or wNumBoxItems) -; [wWhichPokemon] = index (within the inventory) of the item to remove -; [wcf96] = quantity to remove -RemoveItemFromInventory_: ; ce74 (3:4e74) - push hl - inc hl - ld a,[wWhichPokemon] ; index (within the inventory) of the item being removed - sla a - add l - ld l,a - jr nc,.noCarry - inc h -.noCarry - inc hl - ld a,[wcf96] ; quantity being removed - ld e,a - ld a,[hl] ; a = current quantity - sub e - ld [hld],a ; store new quantity - ld [wcf97],a - and a - jr nz,.skipMovingUpSlots -; if the remaining quantity is 0, -; remove the emptied item slot and move up all the following item slots -.moveSlotsUp - ld e,l - ld d,h - inc de - inc de ; de = address of the slot following the emptied one -.loop ; loop to move up the following slots - ld a,[de] - inc de - ld [hli],a - cp a,$ff - jr nz,.loop -; update menu info - xor a - ld [wListScrollOffset],a - ld [wCurrentMenuItem],a - ld [wcc2c],a - ld [wd07e],a - pop hl - ld a,[hl] ; a = number of items in inventory - dec a ; decrement the number of items - ld [hl],a ; store new number of items - ld [wd12a],a - cp a,2 - jr c,.done - ld [wMaxMenuItem],a - jr .done -.skipMovingUpSlots - pop hl -.done - ret - -; wild pokemon data: from 4EB8 to 55C7 - -LoadWildData: ; ceb8 (3:4eb8) - ld hl,WildDataPointers - ld a,[W_CURMAP] - - ; get wild data for current map - ld c,a - ld b,0 - add hl,bc - add hl,bc - ld a,[hli] - ld h,[hl] - ld l,a ; hl now points to wild data for current map - ld a,[hli] - ld [W_GRASSRATE],a - and a - jr z,.NoGrassData ; if no grass data, skip to surfing data - push hl - ld de,W_GRASSMONS ; otherwise, load grass data - ld bc,$0014 - call CopyData - pop hl - ld bc,$0014 - add hl,bc -.NoGrassData - ld a,[hli] - ld [W_WATERRATE],a - and a - ret z ; if no water data, we're done - ld de,W_WATERMONS ; otherwise, load surfing data - ld bc,$0014 - jp CopyData - -INCLUDE "data/wild_mons.asm" - -INCLUDE "engine/items/items.asm" - -DrawBadges: ; ea03 (3:6a03) -; Draw 4x2 gym leader faces, with the faces replaced by -; badges if they are owned. Used in the player status screen. - -; In Japanese versions, names are displayed above faces. -; Instead of removing relevant code, the name graphics were erased. - -; Tile ids for face/badge graphics. - ld de, wTrainerFacingDirection - ld hl, .FaceBadgeTiles - ld bc, 8 - call CopyData - -; Booleans for each badge. - ld hl, wcd49 - ld bc, 8 - xor a - call FillMemory - -; Alter these based on owned badges. - ld de, wcd49 - ld hl, wTrainerFacingDirection - ld a, [W_OBTAINEDBADGES] - ld b, a - ld c, 8 -.CheckBadge - srl b - jr nc, .NextBadge - ld a, [hl] - add 4 ; Badge graphics are after each face - ld [hl], a - ld a, 1 - ld [de], a -.NextBadge - inc hl - inc de - dec c - jr nz, .CheckBadge - -; Draw two rows of badges. - ld hl, wWhichTrade - ld a, $d8 ; [1] - ld [hli], a - ld [hl], $60 ; First name - - hlCoord 2, 11 - ld de, wcd49 - call .DrawBadgeRow - - hlCoord 2, 14 - ld de, wcd49 + 4 -; call .DrawBadgeRow -; ret - -.DrawBadgeRow ; ea4c (3:6a4c) -; Draw 4 badges. - - ld c, 4 -.DrawBadge - push de - push hl - -; Badge no. - ld a, [wWhichTrade] - ld [hli], a - inc a - ld [wWhichTrade], a - -; Names aren't printed if the badge is owned. - ld a, [de] - and a - ld a, [wTrainerEngageDistance] - jr nz, .SkipName - call .PlaceTiles - jr .PlaceBadge - -.SkipName - inc a - inc a - inc hl - -.PlaceBadge - ld [wTrainerEngageDistance], a - ld de, 20 - 1 - add hl, de - ld a, [wTrainerFacingDirection] - call .PlaceTiles - add hl, de - call .PlaceTiles - -; Shift badge array back one byte. - push bc - ld hl, wTrainerFacingDirection + 1 - ld de, wTrainerFacingDirection - ld bc, 8 - call CopyData - pop bc - - pop hl - ld de, 4 - add hl, de - - pop de - inc de - dec c - jr nz, .DrawBadge - ret - -.PlaceTiles - ld [hli], a - inc a - ld [hl], a - inc a - ret - -.FaceBadgeTiles - db $20, $28, $30, $38, $40, $48, $50, $58 - -GymLeaderFaceAndBadgeTileGraphics: ; ea9e (3:6a9e) - INCBIN "gfx/badges.2bpp" - -; replaces a tile block with the one specified in [wNewTileBlockID] -; and redraws the map view if necessary -; b = Y -; c = X -ReplaceTileBlock: ; ee9e (3:6e9e) - call GetPredefRegisters - ld hl, wOverworldMap - ld a, [W_CURMAPWIDTH] - add $6 - ld e, a - ld d, $0 - add hl, de - add hl, de - add hl, de - ld e, $3 - add hl, de - ld e, a - ld a, b - and a - jr z, .addX -; add width * Y -.addWidthYTimesLoop - add hl, de - dec b - jr nz, .addWidthYTimesLoop -.addX - add hl, bc ; add X - ld a, [wNewTileBlockID] - ld [hl], a - ld a, [wCurrentTileBlockMapViewPointer] - ld c, a - ld a, [wCurrentTileBlockMapViewPointer + 1] - ld b, a - call CompareHLWithBC - ret c ; return if the replaced tile block is below the map view in memory - push hl - ld l, e - ld h, $0 - ld e, $6 - ld d, h - add hl, hl - add hl, hl - add hl, de - add hl, bc - pop bc - call CompareHLWithBC - ret c ; return if the replaced tile block is above the map view in memory - -RedrawMapView: ; eedc (3:6edc) - ld a, [W_ISINBATTLE] ; W_ISINBATTLE - inc a - ret z - ld a, [H_AUTOBGTRANSFERENABLED] - push af - ld a, [hTilesetType] - push af - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [hTilesetType], a ; no flower/water BG tile animations - call LoadCurrentMapView - call GoPAL_SET_CF1C - ld hl, wMapViewVRAMPointer - ld a, [hli] - ld h, [hl] - ld l, a - ld de, -2 * 32 - add hl, de - ld a, h - and $3 - or $98 - ld a, l - ld [wHPBarMaxHP], a - ld a, h - ld [wHPBarMaxHP + 1], a - ld a, 2 - ld [$ffbe], a - ld c, 9 ; number of rows of 2x2 tiles (this covers the whole screen) -.redrawRowLoop - push bc - push hl - push hl - ld hl, wTileMap - 2 * 20 - ld de, 20 - ld a, [$ffbe] -.asm_ef1a - add hl, de - dec a - jr nz, .asm_ef1a - call CopyToScreenEdgeTiles - pop hl - ld de, $20 - ld a, [$ffbe] - ld c, a -.asm_ef28 - add hl, de - ld a, h - and $3 - or $98 - dec c - jr nz, .asm_ef28 - ld [H_SCREENEDGEREDRAWADDR + 1], a - ld a, l - ld [H_SCREENEDGEREDRAWADDR], a - ld a, REDRAWROW - ld [H_SCREENEDGEREDRAW], a - call DelayFrame - ld hl, $ffbe - inc [hl] - inc [hl] - pop hl - pop bc - dec c - jr nz, .redrawRowLoop - pop af - ld [hTilesetType], a - pop af - ld [H_AUTOBGTRANSFERENABLED], a - ret - -CompareHLWithBC: ; ef4e (3:6f4e) - ld a, h - sub b - ret nz - ld a, l - sub c - ret - -INCLUDE "engine/overworld/cut.asm" - -MarkTownVisitedAndLoadMissableObjects: ; f113 (3:7113) - ld a, [W_CURMAP] - cp ROUTE_1 - jr nc, .notInTown - ld c, a - ld b, $1 - ld hl, W_TOWNVISITEDFLAG ; mark town as visited (for flying) - predef FlagActionPredef -.notInTown - ld hl, MapHSPointers - ld a, [W_CURMAP] - ld b, $0 - ld c, a - add hl, bc - add hl, bc - ld a, [hli] ; load missable objects pointer in hl - ld h, [hl] - ; fall through - -LoadMissableObjects: ; f132 (3:7132) - ld l, a - push hl - ld de, MapHS00 ; calculate difference between out pointer and the base pointer - ld a, l - sub e - jr nc, .asm_f13c - dec h -.asm_f13c - ld l, a - ld a, h - sub d - ld h, a - ld a, h - ld [H_DIVIDEND], a - ld a, l - ld [H_DIVIDEND+1], a - xor a - ld [H_DIVIDEND+2], a - ld [H_DIVIDEND+3], a - ld a, $3 - ld [H_DIVISOR], a - ld b, $2 - call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours) - ld a, [W_CURMAP] ; W_CURMAP - ld b, a - ld a, [H_DIVIDEND+3] - ld c, a ; store global offset in c - ld de, W_MISSABLEOBJECTLIST - pop hl -.writeMissableObjectsListLoop - ld a, [hli] - cp $ff - jr z, .done ; end of list - cp b - jr nz, .done ; not for current map anymore - ld a, [hli] - inc hl - ld [de], a ; write (map-local) sprite ID - inc de - ld a, c - inc c - ld [de], a ; write (global) missable object index - inc de - jr .writeMissableObjectsListLoop -.done - ld a, $ff - ld [de], a ; write sentinel - ret - -InitializeMissableObjectsFlags: ; f175 (3:7175) - ld hl, W_MISSABLEOBJECTFLAGS - ld bc, $20 - xor a - call FillMemory ; clear missable objects flags - ld hl, MapHS00 - xor a - ld [wd048], a -.missableObjectsLoop - ld a, [hli] - cp $ff ; end of list - ret z - push hl - inc hl - ld a, [hl] - cp Hide - jr nz, .asm_f19d - ld hl, W_MISSABLEOBJECTFLAGS - ld a, [wd048] - ld c, a - ld b, $1 - call MissableObjectFlagAction ; set flag iff Item is hidden -.asm_f19d - ld hl, wd048 - inc [hl] - pop hl - inc hl - inc hl - jr .missableObjectsLoop - -; tests if current sprite is a missable object that is hidden/has been removed -IsObjectHidden: ; f1a6 (3:71a6) - ld a, [H_CURRENTSPRITEOFFSET] - swap a - ld b, a - ld hl, W_MISSABLEOBJECTLIST -.loop - ld a, [hli] - cp $ff - jr z, .notHidden ; not missable -> not hidden - cp b - ld a, [hli] - jr nz, .loop - ld c, a - ld b, $2 - ld hl, W_MISSABLEOBJECTFLAGS - call MissableObjectFlagAction - ld a, c - and a - jr nz, .hidden -.notHidden - xor a -.hidden - ld [$ffe5], a - ret - -; adds missable object (items, leg. pokemon, etc.) to the map -; [wcc4d]: index of the missable object to be added (global index) -ShowObject: ; f1c8 (3:71c8) -ShowObject2: - ld hl, W_MISSABLEOBJECTFLAGS - ld a, [wcc4d] - ld c, a - ld b, $0 - call MissableObjectFlagAction ; reset "removed" flag - jp UpdateSprites - -; removes missable object (items, leg. pokemon, etc.) from the map -; [wcc4d]: index of the missable object to be removed (global index) -HideObject: ; f1d7 (3:71d7) - ld hl, W_MISSABLEOBJECTFLAGS - ld a, [wcc4d] - ld c, a - ld b, $1 - call MissableObjectFlagAction ; set "removed" flag - jp UpdateSprites - -MissableObjectFlagAction: -; identical to FlagAction - - push hl - push de - push bc - - ; bit - ld a, c - ld d, a - and 7 - ld e, a - - ; byte - ld a, d - srl a - srl a - srl a - add l - ld l, a - jr nc, .ok - inc h -.ok - - ; d = 1 << e (bitmask) - inc e - ld d, 1 -.shift - dec e - jr z, .shifted - sla d - jr .shift -.shifted - - ld a, b - and a - jr z, .reset - cp 2 - jr z, .read - -.set - ld a, [hl] - ld b, a - ld a, d - or b - ld [hl], a - jr .done - -.reset - ld a, [hl] - ld b, a - ld a, d - xor $ff - and b - ld [hl], a - jr .done - -.read - ld a, [hl] - ld b, a - ld a, d - and b - -.done - pop bc - pop de - pop hl - ld c, a - ret - -TryPushingBoulder: ; f225 (3:7225) - ld a, [wd728] - bit 0, a ; using Strength? - ret z - ld a, [wFlags_0xcd60] - bit 1, a ; has boulder dust animation from previous push played yet? - ret nz - xor a - ld [$ff8c], a - call IsSpriteInFrontOfPlayer - ld a, [$ff8c] - ld [wBoulderSpriteIndex], a - and a - jp z, ResetBoulderPushFlags - ld hl, wSpriteStateData1 + 1 - ld d, $0 - ld a, [$ff8c] - swap a - ld e, a - add hl, de - res 7, [hl] - call GetSpriteMovementByte2Pointer - ld a, [hl] - cp BOULDER_MOVEMENT_BYTE_2 - jp nz, ResetBoulderPushFlags - ld hl, wFlags_0xcd60 - bit 6, [hl] - set 6, [hl] ; indicate that the player has tried pushing - ret z ; the player must try pushing twice before the boulder will move - ld a, [hJoyHeld] - and $f0 - ret z - predef CheckForCollisionWhenPushingBoulder - ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult] - and a ; was there a collision? - jp nz, ResetBoulderPushFlags - ld a, [hJoyHeld] - ld b, a - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction - cp SPRITE_FACING_UP - jr z, .pushBoulderUp - cp SPRITE_FACING_LEFT - jr z, .pushBoulderLeft - cp SPRITE_FACING_RIGHT - jr z, .pushBoulderRight -.pushBoulderDown - bit 7, b - ret z - ld de, PushBoulderDownMovementData - jr .done -.pushBoulderUp - bit 6, b - ret z - ld de, PushBoulderUpMovementData - jr .done -.pushBoulderLeft - bit 5, b - ret z - ld de, PushBoulderLeftMovementData - jr .done -.pushBoulderRight - bit 4, b - ret z - ld de, PushBoulderRightMovementData -.done - call MoveSprite - ld a, (SFX_02_53 - SFX_Headers_02) / 3 - call PlaySound - ld hl, wFlags_0xcd60 - set 1, [hl] - ret - -PushBoulderUpMovementData: ; f2ad (3:72ad) - db NPC_MOVEMENT_UP,$FF - -PushBoulderDownMovementData: ; f2af (3:72af) - db NPC_MOVEMENT_DOWN,$FF - -PushBoulderLeftMovementData: ; f2b1 (3:72b1) - db NPC_MOVEMENT_LEFT,$FF - -PushBoulderRightMovementData: ; f2b3 (3:72b3) - db NPC_MOVEMENT_RIGHT,$FF - -DoBoulderDustAnimation: ; f2b5 (3:72b5) - ld a, [wd730] - bit 0, a - ret nz - callab AnimateBoulderDust - call DiscardButtonPresses - ld [wJoyIgnore], a - call ResetBoulderPushFlags - set 7, [hl] - ld a, [wBoulderSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteMovementByte2Pointer - ld [hl], $10 - ld a, (SFX_02_56 - SFX_Headers_02) / 3 - jp PlaySound - -ResetBoulderPushFlags: ; f2dd (3:72dd) - ld hl, wFlags_0xcd60 - res 1, [hl] - res 6, [hl] - ret - -_AddPartyMon: ; f2e5 (3:72e5) - ld de, wPartyCount ; wPartyCount - ld a, [wcc49] - and $f - jr z, .asm_f2f2 - ld de, wEnemyPartyCount ; wEnemyPartyCount -.asm_f2f2 - ld a, [de] - inc a - cp PARTY_LENGTH + 1 - ret nc - ld [de], a - ld a, [de] - ld [$ffe4], a - add e - ld e, a - jr nc, .asm_f300 - inc d -.asm_f300 - ld a, [wcf91] - ld [de], a - inc de - ld a, $ff - ld [de], a - ld hl, wPartyMonOT ; wd273 - ld a, [wcc49] - and $f - jr z, .asm_f315 - ld hl, wEnemyMonOT -.asm_f315 - ld a, [$ffe4] - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l - ld hl, wPlayerName ; wd158 - ld bc, $b - call CopyData - ld a, [wcc49] - and a - jr nz, .asm_f33f - ld hl, wPartyMonNicks ; wPartyMonNicks - ld a, [$ffe4] - dec a - call SkipFixedLengthTextEntries - ld a, $2 - ld [wd07d], a - predef AskName -.asm_f33f - ld hl, wPartyMons - ld a, [wcc49] - and $f - jr z, .asm_f34c - ld hl, wEnemyMons -.asm_f34c - ld a, [$ffe4] - dec a - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld e, l - ld d, h - push hl - ld a, [wcf91] - ld [wd0b5], a - call GetMonHeader - ld hl, W_MONHEADER - ld a, [hli] - ld [de], a - inc de - pop hl - push hl - ld a, [wcc49] - and $f - ld a, $98 ; set enemy trainer mon IVs to fixed average values - ld b, $88 - jr nz, .writeFreshMonData - ld a, [wcf91] - ld [wd11e], a - push de - predef IndexToPokedex - pop de - ld a, [wd11e] - dec a - ld c, a - ld b, $2 - ld hl, wPokedexOwned ; wPokedexOwned - call FlagAction - ld a, c - ld [wd153], a - ld a, [wd11e] - dec a - ld c, a - ld b, $1 - push bc - call FlagAction - pop bc - ld hl, wPokedexSeen ; wd30a - call FlagAction - pop hl - push hl - ld a, [W_ISINBATTLE] ; W_ISINBATTLE - and a - jr nz, .copyEnemyMonData - call Random ; generate random IVs - ld b, a - call Random -.writeFreshMonData ; f3b3 - push bc - ld bc, $1b - add hl, bc - pop bc - ld [hli], a - ld [hl], b ; write IVs - ld bc, $fff4 - add hl, bc - ld a, $1 - ld c, a - xor a - ld b, a - call CalcStat ; calc HP stat (set cur Hp to max HP) - ld a, [H_MULTIPLICAND+1] - ld [de], a - inc de - ld a, [H_MULTIPLICAND+2] - ld [de], a - inc de - xor a - ld [de], a ; level (?) - inc de - ld [de], a ; status ailments - inc de - jr .copyMonTypesAndMoves -.copyEnemyMonData - ld bc, $1b - add hl, bc - ld a, [wEnemyMonDVs] ; copy IVs from cur enemy mon - ld [hli], a - ld a, [wEnemyMonDVs + 1] - ld [hl], a - ld a, [wEnemyMonHP] ; copy HP from cur enemy mon - ld [de], a - inc de - ld a, [wEnemyMonHP+1] - ld [de], a - inc de - xor a - ld [de], a ; level (?) - inc de - ld a, [wEnemyMonStatus] ; copy status ailments from cur enemy mon - ld [de], a - inc de -.copyMonTypesAndMoves - ld hl, W_MONHTYPES - ld a, [hli] ; type 1 - ld [de], a - inc de - ld a, [hli] ; type 2 - ld [de], a - inc de - ld a, [hli] ; unused (?) - ld [de], a - ld hl, W_MONHMOVES - ld a, [hli] - inc de - push de - ld [de], a - ld a, [hli] - inc de - ld [de], a - ld a, [hli] - inc de - ld [de], a - ld a, [hli] - inc de - ld [de], a - push de - dec de - dec de - dec de - xor a - ld [wHPBarMaxHP], a - predef WriteMonMoves - pop de - ld a, [wPlayerID] ; set trainer ID to player ID - inc de - ld [de], a - ld a, [wPlayerID + 1] - inc de - ld [de], a - push de - ld a, [W_CURENEMYLVL] - ld d, a - callab CalcExperience - pop de - inc de - ld a, [H_MULTIPLICAND] ; write experience - ld [de], a - inc de - ld a, [H_MULTIPLICAND+1] - ld [de], a - inc de - ld a, [H_MULTIPLICAND+2] - ld [de], a - xor a - ld b, $a -.writeEVsLoop ; set all EVs to 0 - inc de - ld [de], a - dec b - jr nz, .writeEVsLoop - inc de - inc de - pop hl - call AddPartyMon_WriteMovePP - inc de - ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL - ld [de], a - inc de - ld a, [W_ISINBATTLE] ; W_ISINBATTLE - dec a - jr nz, .calcFreshStats - ld hl, wEnemyMonMaxHP ; wEnemyMonMaxHP - ld bc, $a - call CopyData ; copy stats of cur enemy mon - pop hl - jr .done -.calcFreshStats - pop hl - ld bc, $10 - add hl, bc - ld b, $0 - call CalcStats ; calculate fresh set of stats -.done - scf - ret - -LoadMovePPs: ; f473 (3:7473) - call GetPredefRegisters - ; fallthrough -AddPartyMon_WriteMovePP: ; f476 (3:7476) - ld b, $4 -.pploop - ld a, [hli] ; read move ID - and a - jr z, .empty - dec a - push hl - push de - push bc - ld hl, Moves - ld bc, $6 - call AddNTimes - ld de, wcd6d - ld a, BANK(Moves) - call FarCopyData - pop bc - pop de - pop hl - ld a, [wcd72] ; sixth move byte = pp -.empty - inc de - ld [de], a - dec b - jr nz, .pploop ; there are still moves to read - ret - -; adds enemy mon [wcf91] (at position [wWhichPokemon] in enemy list) to own party -; used in the cable club trade center -_AddEnemyMonToPlayerParty: ; f49d (3:749d) - ld hl, wPartyCount - ld a, [hl] - cp PARTY_LENGTH - scf - ret z ; party full, return failure - inc a - ld [hl], a ; add 1 to party members - ld c, a - ld b, $0 - add hl, bc - ld a, [wcf91] - ld [hli], a ; add mon as last list entry - ld [hl], $ff ; write new sentinel - ld hl, wPartyMons - ld a, [wPartyCount] - dec a - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld e, l - ld d, h - ld hl, wLoadedMon - call CopyData ; write new mon's data (from wLoadedMon) - ld hl, wPartyMonOT - ld a, [wPartyCount] - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l - ld hl, wEnemyMonOT - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries - ld bc, $000b - call CopyData ; write new mon's OT name (from an enemy mon) - ld hl, wPartyMonNicks - ld a, [wPartyCount] - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l - ld hl, wEnemyMonNicks - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries - ld bc, $000b - call CopyData ; write new mon's nickname (from an enemy mon) - ld a, [wcf91] - ld [wd11e], a - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld b, $1 - ld hl, wPokedexOwned - push bc - call FlagAction ; add to owned pokemon - pop bc - ld hl, wPokedexSeen - call FlagAction ; add to seen pokemon - and a - ret ; return success - -Func_f51e: ; f51e (3:751e) - ld a, [wcf95] - and a - jr z, .checkPartyMonSlots - cp $2 - jr z, .checkPartyMonSlots - cp $3 - ld hl, wDayCareMon - jr z, .asm_f575 - ld hl, W_NUMINBOX ; wda80 - ld a, [hl] - cp MONS_PER_BOX - jr nz, .partyOrBoxNotFull - jr .boxFull -.checkPartyMonSlots - ld hl, wPartyCount ; wPartyCount - ld a, [hl] - cp PARTY_LENGTH - jr nz, .partyOrBoxNotFull -.boxFull - scf - ret -.partyOrBoxNotFull - inc a - ld [hl], a ; increment number of mons in party/box - ld c, a - ld b, $0 - add hl, bc - ld a, [wcf95] - cp $2 - ld a, [wDayCareMon] - jr z, .asm_f556 - ld a, [wcf91] -.asm_f556 - ld [hli], a ; write new mon ID - ld [hl], $ff ; write new sentinel - ld a, [wcf95] - dec a - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 ; $2c - ld a, [wPartyCount] ; wPartyCount - jr nz, .skipToNewMonEntry - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 ; $21 - ld a, [W_NUMINBOX] ; wda80 -.skipToNewMonEntry - dec a - call AddNTimes -.asm_f575 - push hl - ld e, l - ld d, h - ld a, [wcf95] - and a - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 ; $21 - jr z, .asm_f591 - cp $2 - ld hl, wDayCareMon - jr z, .asm_f597 - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 ; $2c -.asm_f591 - ld a, [wWhichPokemon] ; wWhichPokemon - call AddNTimes -.asm_f597 - push hl - push de - ld bc, wBoxMon2 - wBoxMon1 - call CopyData - pop de - pop hl - ld a, [wcf95] - and a - jr z, .asm_f5b4 - cp $2 - jr z, .asm_f5b4 - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld a, [hl] - inc de - inc de - inc de - ld [de], a -.asm_f5b4 - ld a, [wcf95] - cp $3 - ld de, W_DAYCAREMONOT - jr z, .asm_f5d3 - dec a - ld hl, wPartyMonOT ; wd273 - ld a, [wPartyCount] ; wPartyCount - jr nz, .asm_f5cd - ld hl, wBoxMonOT - ld a, [W_NUMINBOX] ; wda80 -.asm_f5cd - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l -.asm_f5d3 - ld hl, wBoxMonOT - ld a, [wcf95] - and a - jr z, .asm_f5e6 - ld hl, W_DAYCAREMONOT - cp $2 - jr z, .asm_f5ec - ld hl, wPartyMonOT ; wd273 -.asm_f5e6 - ld a, [wWhichPokemon] ; wWhichPokemon - call SkipFixedLengthTextEntries -.asm_f5ec - ld bc, $b - call CopyData - ld a, [wcf95] - cp $3 - ld de, W_DAYCAREMONNAME - jr z, .asm_f611 - dec a - ld hl, wPartyMonNicks ; wPartyMonNicks - ld a, [wPartyCount] ; wPartyCount - jr nz, .asm_f60b - ld hl, wBoxMonNicks - ld a, [W_NUMINBOX] ; wda80 -.asm_f60b - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l -.asm_f611 - ld hl, wBoxMonNicks - ld a, [wcf95] - and a - jr z, .asm_f624 - ld hl, W_DAYCAREMONNAME - cp $2 - jr z, .asm_f62a - ld hl, wPartyMonNicks ; wPartyMonNicks -.asm_f624 - ld a, [wWhichPokemon] ; wWhichPokemon - call SkipFixedLengthTextEntries -.asm_f62a - ld bc, $b - call CopyData - pop hl - ld a, [wcf95] - cp $1 - jr z, .asm_f664 - cp $3 - jr z, .asm_f664 - push hl - srl a - add $2 - ld [wcc49], a - call LoadMonData - callba CalcLevelFromExperience - ld a, d - ld [W_CURENEMYLVL], a ; W_CURENEMYLVL - pop hl - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld [hli], a - ld d, h - ld e, l - ld bc, $ffee - add hl, bc - ld b, $1 - call CalcStats -.asm_f664 - and a - ret - - -FlagActionPredef: - call GetPredefRegisters - -FlagAction: -; Perform action b on bit c -; in the bitfield at hl. -; 0: reset -; 1: set -; 2: read -; Return the result in c. - - push hl - push de - push bc - - ; bit - ld a, c - ld d, a - and 7 - ld e, a - - ; byte - ld a, d - srl a - srl a - srl a - add l - ld l, a - jr nc, .ok - inc h -.ok - - ; d = 1 << e (bitmask) - inc e - ld d, 1 -.shift - dec e - jr z, .shifted - sla d - jr .shift -.shifted - - ld a, b - and a - jr z, .reset - cp 2 - jr z, .read - -.set - ld b, [hl] - ld a, d - or b - ld [hl], a - jr .done - -.reset - ld b, [hl] - ld a, d - xor $ff - and b - ld [hl], a - jr .done - -.read - ld b, [hl] - ld a, d - and b -.done - pop bc - pop de - pop hl - ld c, a - ret - - -HealParty: -; Restore HP and PP. - - ld hl, wPartySpecies - ld de, wPartyMon1HP -.healmon - ld a, [hli] - cp $ff - jr z, .done - - push hl - push de - - ld hl, wPartyMon1Status - wPartyMon1HP - add hl, de - xor a - ld [hl], a - - push de - ld b, NUM_MOVES ; A Pokémon has 4 moves -.pp - ld hl, wPartyMon1Moves - wPartyMon1HP - add hl, de - - ld a, [hl] - and a - jr z, .nextmove - - dec a - ld hl, wPartyMon1PP - wPartyMon1HP - add hl, de - - push hl - push de - push bc - - ld hl, Moves - ld bc, $0006 - call AddNTimes - ld de, wcd6d - ld a, BANK(Moves) - call FarCopyData - ld a, [wcd72] ; default pp - - pop bc - pop de - pop hl - - inc de - push bc - ld b, a - ld a, [hl] - and $c0 - add b - ld [hl], a - pop bc - -.nextmove - dec b - jr nz, .pp - pop de - - ld hl, wPartyMon1MaxHP - wPartyMon1HP - add hl, de - ld a, [hli] - ld [de], a - inc de - ld a, [hl] - ld [de], a - - pop de - pop hl - - push hl - ld bc, wPartyMon2 - wPartyMon1 - ld h, d - ld l, e - add hl, bc - ld d, h - ld e, l - pop hl - jr .healmon - -.done - xor a - ld [wWhichPokemon], a - ld [wd11e], a - - ld a, [wPartyCount] - ld b, a -.ppup - push bc - call RestoreBonusPP - pop bc - ld hl, wWhichPokemon - inc [hl] - dec b - jr nz, .ppup - ret - - -DivideBCDPredef:: -DivideBCDPredef2:: -DivideBCDPredef3:: -DivideBCDPredef4:: - call GetPredefRegisters - -DivideBCD:: - xor a - ld [$ffa5], a - ld [$ffa6], a - ld [$ffa7], a - ld d, $1 -.asm_f72a - ld a, [$ffa2] - and $f0 - jr nz, .asm_f75b - inc d - ld a, [$ffa2] - swap a - and $f0 - ld b, a - ld a, [$ffa3] - swap a - ld [$ffa3], a - and $f - or b - ld [$ffa2], a - ld a, [$ffa3] - and $f0 - ld b, a - ld a, [$ffa4] - swap a - ld [$ffa4], a - and $f - or b - ld [$ffa3], a - ld a, [$ffa4] - and $f0 - ld [$ffa4], a - jr .asm_f72a -.asm_f75b - push de - push de - call Func_f800 - pop de - ld a, b - swap a - and $f0 - ld [$ffa5], a - dec d - jr z, .asm_f7bc - push de - call Func_f7d7 - call Func_f800 - pop de - ld a, [$ffa5] - or b - ld [$ffa5], a - dec d - jr z, .asm_f7bc - push de - call Func_f7d7 - call Func_f800 - pop de - ld a, b - swap a - and $f0 - ld [$ffa6], a - dec d - jr z, .asm_f7bc - push de - call Func_f7d7 - call Func_f800 - pop de - ld a, [$ffa6] - or b - ld [$ffa6], a - dec d - jr z, .asm_f7bc - push de - call Func_f7d7 - call Func_f800 - pop de - ld a, b - swap a - and $f0 - ld [$ffa7], a - dec d - jr z, .asm_f7bc - push de - call Func_f7d7 - call Func_f800 - pop de - ld a, [$ffa7] - or b - ld [$ffa7], a -.asm_f7bc - ld a, [$ffa5] - ld [$ffa2], a - ld a, [$ffa6] - ld [$ffa3], a - ld a, [$ffa7] - ld [$ffa4], a - pop de - ld a, $6 - sub d - and a - ret z -.asm_f7ce - push af - call Func_f7d7 - pop af - dec a - jr nz, .asm_f7ce - ret - -Func_f7d7: ; f7d7 (3:77d7) - ld a, [$ffa4] - swap a - and $f - ld b, a - ld a, [$ffa3] - swap a - ld [$ffa3], a - and $f0 - or b - ld [$ffa4], a - ld a, [$ffa3] - and $f - ld b, a - ld a, [$ffa2] - swap a - ld [$ffa2], a - and $f0 - or b - ld [$ffa3], a - ld a, [$ffa2] - and $f - ld [$ffa2], a - ret - -Func_f800: ; f800 (3:7800) - ld bc, $3 -.asm_f803 - ld de, $ff9f - ld hl, $ffa2 - push bc - call StringCmp - pop bc - ret c - inc b - ld de, $ffa1 - ld hl, $ffa4 - push bc - call SubBCD - pop bc - jr .asm_f803 - - -AddBCDPredef:: - call GetPredefRegisters - -AddBCD:: - and a - ld b, c -.add - ld a, [de] - adc [hl] - daa - ld [de], a - dec de - dec hl - dec c - jr nz, .add - jr nc, .done - ld a, $99 - inc de -.fill - ld [de], a - inc de - dec b - jr nz, .fill -.done - ret - - -SubBCDPredef:: - call GetPredefRegisters - -SubBCD:: - and a - ld b, c -.sub - ld a, [de] - sbc [hl] - daa - ld [de], a - dec de - dec hl - dec c - jr nz, .sub - jr nc, .done - ld a, $00 - inc de -.fill - ld [de], a - inc de - dec b - jr nz, .fill - scf -.done - ret - - -InitPlayerData: -InitPlayerData2: - - call Random - ld a, [hRandomSub] - ld [wPlayerID], a - - call Random - ld a, [hRandomAdd] - ld [wPlayerID + 1], a - - ld a, $ff - ld [wd71b], a ; XXX what's this? - - ld hl, wPartyCount - call InitializeEmptyList - ld hl, W_NUMINBOX - call InitializeEmptyList - ld hl, wNumBagItems - call InitializeEmptyList - ld hl, wNumBoxItems - call InitializeEmptyList - -START_MONEY EQU $3000 - ld hl, wPlayerMoney + 1 - ld a, START_MONEY / $100 - ld [hld], a - xor a - ld [hli], a - inc hl - ld [hl], a - - ld [wcc49], a - - ld hl, W_OBTAINEDBADGES - ld [hli], a - - ld [hl], a - - ld hl, wPlayerCoins - ld [hli], a - ld [hl], a - - ld hl, W_GAMEPROGRESSFLAGS - ld bc, $c8 - call FillMemory ; clear all game progress flags - - jp InitializeMissableObjectsFlags - -InitializeEmptyList: - xor a ; count - ld [hli], a - dec a ; terminator - ld [hl], a - ret - - -IsItemInBag_: ; f8a5 (3:78a5) - call GetPredefRegisters - ld hl, wNumBagItems ; wNumBagItems -.asm_f8ab - inc hl - ld a, [hli] - cp $ff - jr z, .asm_f8b7 - cp b - jr nz, .asm_f8ab - ld a, [hl] - ld b, a - ret -.asm_f8b7 - ld b, $0 - ret - -FindPathToPlayer: ; f8ba (3:78ba) - xor a - ld hl, $ff97 - ld [hli], a - ld [hli], a - ld [hli], a - ld [hl], a - ld hl, wNPCMovementDirections2 - ld de, $0 -.loop - ld a, [$ff99] - ld b, a - ld a, [$ff95] ; Y distance in steps - call CalcDifference - ld d, a - and a - jr nz, .asm_f8da - ld a, [$ff98] - set 0, a - ld [$ff98], a -.asm_f8da - ld a, [$ff9a] - ld b, a - ld a, [$ff96] ; X distance in steps - call CalcDifference - ld e, a - and a - jr nz, .asm_f8ec - ld a, [$ff98] - set 1, a - ld [$ff98], a -.asm_f8ec - ld a, [$ff98] - cp $3 - jr z, .done - ld a, e - cp d - jr c, .asm_f90a - ld a, [$ff9d] - bit 1, a - jr nz, .asm_f900 - ld d, NPC_MOVEMENT_RIGHT - jr .asm_f902 -.asm_f900 - ld d, NPC_MOVEMENT_LEFT -.asm_f902 - ld a, [$ff9a] - add $1 - ld [$ff9a], a - jr .asm_f91c -.asm_f90a - ld a, [$ff9d] - bit 0, a - jr nz, .asm_f914 - ld d, NPC_MOVEMENT_DOWN - jr .asm_f916 -.asm_f914 - ld d, NPC_MOVEMENT_UP -.asm_f916 - ld a, [$ff99] - add $1 - ld [$ff99], a -.asm_f91c - ld a, d - ld [hli], a - ld a, [$ff97] - inc a - ld [$ff97], a - jp .loop -.done - ld [hl], $ff - ret - -CalcPositionOfPlayerRelativeToNPC: ; f929 (3:7929) - xor a - ld [$ff9d], a - ld a, [wSpriteStateData1 + 4] ; player's sprite screen Y position in pixels - ld d, a - ld a, [wSpriteStateData1 + 6] ; player's sprite screen X position in pixels - ld e, a - ld hl, wSpriteStateData1 - ld a, [$ff95] ; sprite offset - add l - add $4 - ld l, a - jr nc, .noCarry - inc h -.noCarry - ld a, d - ld b, a - ld a, [hli] ; NPC sprite screen Y position in pixels - call CalcDifference - jr nc, .NPCSouthOfOrAlignedWithPlayer -.NPCNorthOfPlayer - push hl - ld hl, $ff9d - bit 0, [hl] - set 0, [hl] - pop hl - jr .divideYDistance -.NPCSouthOfOrAlignedWithPlayer - push hl - ld hl, $ff9d - bit 0, [hl] - res 0, [hl] - pop hl -.divideYDistance - push hl - ld hl, $ffe5 - ld [hli], a - ld a, 16 - ld [hli], a - call DivideBytes ; divide Y absolute distance by 16 - ld a, [hl] ; quotient - ld [$ff95], a - pop hl - inc hl - ld b, e - ld a, [hl] ; NPC sprite screen X position in pixels - call CalcDifference - jr nc, .NPCEastOfOrAlignedWithPlayer -.NPCWestOfPlayer - push hl - ld hl, $ff9d - bit 1, [hl] - set 1, [hl] - pop hl - jr .divideXDistance -.NPCEastOfOrAlignedWithPlayer - push hl - ld hl, $ff9d - bit 1, [hl] - res 1, [hl] - pop hl -.divideXDistance - ld [$ffe5], a - ld a, 16 - ld [$ffe6], a - call DivideBytes ; divide X absolute distance by 16 - ld a, [$ffe7] ; quotient - ld [$ff96], a - ld a, [$ff9b] - and a - ret z - ld a, [$ff9d] - cpl - and $3 - ld [$ff9d], a - ret - -ConvertNPCMovementDirectionsToJoypadMasks: ; f9a0 (3:79a0) - ld a, [$ff95] - ld [wNPCMovementDirections2Index], a - dec a - ld de, wSimulatedJoypadStatesEnd - ld hl, wNPCMovementDirections2 - add l - ld l, a - jr nc, .loop - inc h -.loop - ld a, [hld] - call ConvertNPCMovementDirectionToJoypadMask - ld [de], a - inc de - ld a, [$ff95] - dec a - ld [$ff95], a - jr nz, .loop - ret - -ConvertNPCMovementDirectionToJoypadMask: ; f9bf (3:79bf) - push hl - ld b, a - ld hl, NPCMovementDirectionsToJoypadMasksTable -.loop - ld a, [hli] - cp $ff - jr z, .done - cp b - jr z, .loadJoypadMask - inc hl - jr .loop -.loadJoypadMask - ld a, [hl] -.done - pop hl - ret - -NPCMovementDirectionsToJoypadMasksTable: ; f9d2 (3:79d2) - db NPC_MOVEMENT_UP, D_UP - db NPC_MOVEMENT_DOWN, D_DOWN - db NPC_MOVEMENT_LEFT, D_LEFT - db NPC_MOVEMENT_RIGHT, D_RIGHT - db $ff - -Func_f9db: ; f9db (3:79db) - ret - -INCLUDE "engine/hp_bar.asm" - -INCLUDE "engine/hidden_object_functions3.asm" - - -SECTION "NPC Sprites 1", ROMX, BANK[NPC_SPRITES_1] - -OakAideSprite: INCBIN "gfx/sprites/oak_aide.2bpp" -RockerSprite: INCBIN "gfx/sprites/rocker.2bpp" -SwimmerSprite: INCBIN "gfx/sprites/swimmer.2bpp" -WhitePlayerSprite: INCBIN "gfx/sprites/white_player.2bpp" -GymHelperSprite: INCBIN "gfx/sprites/gym_helper.2bpp" -OldPersonSprite: INCBIN "gfx/sprites/old_person.2bpp" -MartGuySprite: INCBIN "gfx/sprites/mart_guy.2bpp" -FisherSprite: INCBIN "gfx/sprites/fisher.2bpp" -OldMediumWomanSprite: INCBIN "gfx/sprites/old_medium_woman.2bpp" -NurseSprite: INCBIN "gfx/sprites/nurse.2bpp" -CableClubWomanSprite: INCBIN "gfx/sprites/cable_club_woman.2bpp" -MrMasterballSprite: INCBIN "gfx/sprites/mr_masterball.2bpp" -LaprasGiverSprite: INCBIN "gfx/sprites/lapras_giver.2bpp" -WardenSprite: INCBIN "gfx/sprites/warden.2bpp" -SsCaptainSprite: INCBIN "gfx/sprites/ss_captain.2bpp" -Fisher2Sprite: INCBIN "gfx/sprites/fisher2.2bpp" -BlackbeltSprite: INCBIN "gfx/sprites/blackbelt.2bpp" -GuardSprite: INCBIN "gfx/sprites/guard.2bpp" -BallSprite: INCBIN "gfx/sprites/ball.2bpp" -OmanyteSprite: INCBIN "gfx/sprites/omanyte.2bpp" -BoulderSprite: INCBIN "gfx/sprites/boulder.2bpp" -PaperSheetSprite: INCBIN "gfx/sprites/paper_sheet.2bpp" -BookMapDexSprite: INCBIN "gfx/sprites/book_map_dex.2bpp" -ClipboardSprite: INCBIN "gfx/sprites/clipboard.2bpp" -SnorlaxSprite: INCBIN "gfx/sprites/snorlax.2bpp" -OldAmberSprite: INCBIN "gfx/sprites/old_amber.2bpp" -LyingOldManSprite: INCBIN "gfx/sprites/lying_old_man.2bpp" - - -SECTION "Graphics", ROMX, BANK[GFX] - -PokemonLogoGraphics: INCBIN "gfx/pokemon_logo.2bpp" -FontGraphics: INCBIN "gfx/font.1bpp" -ABTiles: INCBIN "gfx/AB.2bpp" -HpBarAndStatusGraphics: INCBIN "gfx/hp_bar_and_status.2bpp" -BattleHudTiles1: INCBIN "gfx/battle_hud1.1bpp" -BattleHudTiles2: INCBIN "gfx/battle_hud2.1bpp" -BattleHudTiles3: INCBIN "gfx/battle_hud3.1bpp" -NintendoCopyrightLogoGraphics: INCBIN "gfx/copyright.2bpp" -GamefreakLogoGraphics: INCBIN "gfx/gamefreak.2bpp" -TextBoxGraphics: INCBIN "gfx/text_box.2bpp" -PokedexTileGraphics: INCBIN "gfx/pokedex.2bpp" -WorldMapTileGraphics: INCBIN "gfx/town_map.2bpp" -PlayerCharacterTitleGraphics: INCBIN "gfx/player_title.2bpp" - - -SECTION "Battle (bank 4)", ROMX, BANK[$4] - -INCLUDE "engine/overworld/is_player_just_outside_map.asm" -INCLUDE "engine/menu/status_screen.asm" -INCLUDE "engine/menu/party_menu.asm" - -RedPicFront:: INCBIN "pic/trainer/red.pic" -ShrinkPic1:: INCBIN "pic/trainer/shrink1.pic" -ShrinkPic2:: INCBIN "pic/trainer/shrink2.pic" - -INCLUDE "engine/turn_sprite.asm" -INCLUDE "engine/menu/start_sub_menus.asm" -INCLUDE "engine/items/tms.asm" -INCLUDE "engine/battle/end_of_battle.asm" -INCLUDE "engine/battle/wild_encounters.asm" -INCLUDE "engine/battle/moveEffects/recoil_effect.asm" -INCLUDE "engine/battle/moveEffects/conversion_effect.asm" -INCLUDE "engine/battle/moveEffects/haze_effect.asm" -INCLUDE "engine/battle/get_trainer_name.asm" - - -SECTION "NPC Sprites 2", ROMX, BANK[NPC_SPRITES_2] - -RedCyclingSprite: INCBIN "gfx/sprites/cycling.2bpp" -RedSprite: INCBIN "gfx/sprites/red.2bpp" -BlueSprite: INCBIN "gfx/sprites/blue.2bpp" -OakSprite: INCBIN "gfx/sprites/oak.2bpp" -BugCatcherSprite: INCBIN "gfx/sprites/bug_catcher.2bpp" -SlowbroSprite: INCBIN "gfx/sprites/slowbro.2bpp" -LassSprite: INCBIN "gfx/sprites/lass.2bpp" -BlackHairBoy1Sprite: INCBIN "gfx/sprites/black_hair_boy_1.2bpp" -LittleGirlSprite: INCBIN "gfx/sprites/little_girl.2bpp" -BirdSprite: INCBIN "gfx/sprites/bird.2bpp" -FatBaldGuySprite: INCBIN "gfx/sprites/fat_bald_guy.2bpp" -GamblerSprite: INCBIN "gfx/sprites/gambler.2bpp" -BlackHairBoy2Sprite: INCBIN "gfx/sprites/black_hair_boy_2.2bpp" -GirlSprite: INCBIN "gfx/sprites/girl.2bpp" -HikerSprite: INCBIN "gfx/sprites/hiker.2bpp" -FoulardWomanSprite: INCBIN "gfx/sprites/foulard_woman.2bpp" -GentlemanSprite: INCBIN "gfx/sprites/gentleman.2bpp" -DaisySprite: INCBIN "gfx/sprites/daisy.2bpp" -BikerSprite: INCBIN "gfx/sprites/biker.2bpp" -SailorSprite: INCBIN "gfx/sprites/sailor.2bpp" -CookSprite: INCBIN "gfx/sprites/cook.2bpp" -BikeShopGuySprite: INCBIN "gfx/sprites/bike_shop_guy.2bpp" -MrFujiSprite: INCBIN "gfx/sprites/mr_fuji.2bpp" -GiovanniSprite: INCBIN "gfx/sprites/giovanni.2bpp" -RocketSprite: INCBIN "gfx/sprites/rocket.2bpp" -MediumSprite: INCBIN "gfx/sprites/medium.2bpp" -WaiterSprite: INCBIN "gfx/sprites/waiter.2bpp" -ErikaSprite: INCBIN "gfx/sprites/erika.2bpp" -MomGeishaSprite: INCBIN "gfx/sprites/mom_geisha.2bpp" -BrunetteGirlSprite: INCBIN "gfx/sprites/brunette_girl.2bpp" -LanceSprite: INCBIN "gfx/sprites/lance.2bpp" -MomSprite: INCBIN "gfx/sprites/mom.2bpp" -BaldingGuySprite: INCBIN "gfx/sprites/balding_guy.2bpp" -YoungBoySprite: INCBIN "gfx/sprites/young_boy.2bpp" -GameboyKidSprite: INCBIN "gfx/sprites/gameboy_kid.2bpp" -ClefairySprite: INCBIN "gfx/sprites/clefairy.2bpp" -AgathaSprite: INCBIN "gfx/sprites/agatha.2bpp" -BrunoSprite: INCBIN "gfx/sprites/bruno.2bpp" -LoreleiSprite: INCBIN "gfx/sprites/lorelei.2bpp" -SeelSprite: INCBIN "gfx/sprites/seel.2bpp" - - -SECTION "Battle (bank 5)", ROMX, BANK[$5] - -INCLUDE "engine/load_pokedex_tiles.asm" -INCLUDE "engine/overworld/map_sprites.asm" -INCLUDE "engine/overworld/emotion_bubbles.asm" -INCLUDE "engine/evolve_trade.asm" -INCLUDE "engine/battle/moveEffects/substitute_effect.asm" -INCLUDE "engine/menu/pc.asm" - - -SECTION "bank6",ROMX,BANK[$6] - -INCLUDE "data/mapHeaders/celadoncity.asm" -INCLUDE "data/mapObjects/celadoncity.asm" -CeladonCityBlocks: INCBIN "maps/celadoncity.blk" - -INCLUDE "data/mapHeaders/pallettown.asm" -INCLUDE "data/mapObjects/pallettown.asm" -PalletTownBlocks: INCBIN "maps/pallettown.blk" - -INCLUDE "data/mapHeaders/viridiancity.asm" -INCLUDE "data/mapObjects/viridiancity.asm" -ViridianCityBlocks: INCBIN "maps/viridiancity.blk" - -INCLUDE "data/mapHeaders/pewtercity.asm" -INCLUDE "data/mapObjects/pewtercity.asm" -PewterCityBlocks: INCBIN "maps/pewtercity.blk" - -INCLUDE "data/mapHeaders/ceruleancity.asm" -INCLUDE "data/mapObjects/ceruleancity.asm" -CeruleanCityBlocks: INCBIN "maps/ceruleancity.blk" - -INCLUDE "data/mapHeaders/vermilioncity.asm" -INCLUDE "data/mapObjects/vermilioncity.asm" -VermilionCityBlocks: INCBIN "maps/vermilioncity.blk" - -INCLUDE "data/mapHeaders/fuchsiacity.asm" -INCLUDE "data/mapObjects/fuchsiacity.asm" -FuchsiaCityBlocks: INCBIN "maps/fuchsiacity.blk" - -INCLUDE "engine/play_time.asm" - -INCLUDE "scripts/pallettown.asm" -INCLUDE "scripts/viridiancity.asm" -INCLUDE "scripts/pewtercity.asm" -INCLUDE "scripts/ceruleancity.asm" -INCLUDE "scripts/vermilioncity.asm" -INCLUDE "scripts/celadoncity.asm" -INCLUDE "scripts/fuchsiacity.asm" - -INCLUDE "data/mapHeaders/blueshouse.asm" -INCLUDE "scripts/blueshouse.asm" -INCLUDE "data/mapObjects/blueshouse.asm" -BluesHouseBlocks: INCBIN "maps/blueshouse.blk" - -INCLUDE "data/mapHeaders/vermilionhouse3.asm" -INCLUDE "scripts/vermilionhouse3.asm" -INCLUDE "data/mapObjects/vermilionhouse3.asm" -VermilionHouse3Blocks: INCBIN "maps/vermilionhouse3.blk" - -INCLUDE "data/mapHeaders/indigoplateaulobby.asm" -INCLUDE "scripts/indigoplateaulobby.asm" -INCLUDE "data/mapObjects/indigoplateaulobby.asm" -IndigoPlateauLobbyBlocks: INCBIN "maps/indigoplateaulobby.blk" - -INCLUDE "data/mapHeaders/silphco4.asm" -INCLUDE "scripts/silphco4.asm" -INCLUDE "data/mapObjects/silphco4.asm" -SilphCo4Blocks: INCBIN "maps/silphco4.blk" - -INCLUDE "data/mapHeaders/silphco5.asm" -INCLUDE "scripts/silphco5.asm" -INCLUDE "data/mapObjects/silphco5.asm" -SilphCo5Blocks: INCBIN "maps/silphco5.blk" - -INCLUDE "data/mapHeaders/silphco6.asm" -INCLUDE "scripts/silphco6.asm" -INCLUDE "data/mapObjects/silphco6.asm" -SilphCo6Blocks: INCBIN "maps/silphco6.blk" - -INCLUDE "engine/overworld/npc_movement.asm" -INCLUDE "engine/overworld/doors.asm" -INCLUDE "engine/overworld/ledges.asm" - - -SECTION "bank7",ROMX,BANK[$7] - -INCLUDE "data/mapHeaders/cinnabarisland.asm" -INCLUDE "data/mapObjects/cinnabarisland.asm" -CinnabarIslandBlocks: INCBIN "maps/cinnabarisland.blk" - -INCLUDE "data/mapHeaders/route1.asm" -INCLUDE "data/mapObjects/route1.asm" -Route1Blocks: INCBIN "maps/route1.blk" - -UndergroundPathEntranceRoute8Blocks: INCBIN "maps/undergroundpathentranceroute8.blk" - -OaksLabBlocks: INCBIN "maps/oakslab.blk" - -Route16HouseBlocks: -Route2HouseBlocks: -SaffronHouse1Blocks: -SaffronHouse2Blocks: -VermilionHouse1Blocks: -NameRaterBlocks: -LavenderHouse1Blocks: -LavenderHouse2Blocks: -CeruleanHouse1Blocks: -PewterHouse1Blocks: -PewterHouse2Blocks: -ViridianHouseBlocks: INCBIN "maps/viridianhouse.blk" - -CeladonMansion5Blocks: -SchoolBlocks: INCBIN "maps/school.blk" - -CeruleanHouseTrashedBlocks: INCBIN "maps/ceruleanhousetrashed.blk" - -DiglettsCaveEntranceRoute11Blocks: -DiglettsCaveRoute2Blocks: INCBIN "maps/diglettscaveroute2.blk" - -INCLUDE "text/monster_names.asm" - -INCLUDE "engine/clear_save.asm" - -INCLUDE "engine/predefs7.asm" - -INCLUDE "scripts/cinnabarisland.asm" - -INCLUDE "scripts/route1.asm" - -INCLUDE "data/mapHeaders/oakslab.asm" -INCLUDE "scripts/oakslab.asm" -INCLUDE "data/mapObjects/oakslab.asm" - -INCLUDE "data/mapHeaders/viridianmart.asm" -INCLUDE "scripts/viridianmart.asm" -INCLUDE "data/mapObjects/viridianmart.asm" -ViridianMartBlocks: INCBIN "maps/viridianmart.blk" - -INCLUDE "data/mapHeaders/school.asm" -INCLUDE "scripts/school.asm" -INCLUDE "data/mapObjects/school.asm" - -INCLUDE "data/mapHeaders/viridianhouse.asm" -INCLUDE "scripts/viridianhouse.asm" -INCLUDE "data/mapObjects/viridianhouse.asm" - -INCLUDE "data/mapHeaders/pewterhouse1.asm" -INCLUDE "scripts/pewterhouse1.asm" -INCLUDE "data/mapObjects/pewterhouse1.asm" - -INCLUDE "data/mapHeaders/pewterhouse2.asm" -INCLUDE "scripts/pewterhouse2.asm" -INCLUDE "data/mapObjects/pewterhouse2.asm" - -INCLUDE "data/mapHeaders/ceruleanhousetrashed.asm" -INCLUDE "scripts/ceruleanhousetrashed.asm" -INCLUDE "data/mapObjects/ceruleanhousetrashed.asm" - -INCLUDE "data/mapHeaders/ceruleanhouse1.asm" -INCLUDE "scripts/ceruleanhouse1.asm" -INCLUDE "data/mapObjects/ceruleanhouse1.asm" - -INCLUDE "data/mapHeaders/bikeshop.asm" -INCLUDE "scripts/bikeshop.asm" -INCLUDE "data/mapObjects/bikeshop.asm" -BikeShopBlocks: INCBIN "maps/bikeshop.blk" - -INCLUDE "data/mapHeaders/lavenderhouse1.asm" -INCLUDE "scripts/lavenderhouse1.asm" -INCLUDE "data/mapObjects/lavenderhouse1.asm" - -INCLUDE "data/mapHeaders/lavenderhouse2.asm" -INCLUDE "scripts/lavenderhouse2.asm" -INCLUDE "data/mapObjects/lavenderhouse2.asm" - -INCLUDE "data/mapHeaders/namerater.asm" -INCLUDE "scripts/namerater.asm" -INCLUDE "data/mapObjects/namerater.asm" - -INCLUDE "data/mapHeaders/vermilionhouse1.asm" -INCLUDE "scripts/vermilionhouse1.asm" -INCLUDE "data/mapObjects/vermilionhouse1.asm" - -INCLUDE "data/mapHeaders/vermiliondock.asm" -INCLUDE "scripts/vermiliondock.asm" -INCLUDE "data/mapObjects/vermiliondock.asm" -VermilionDockBlocks: INCBIN "maps/vermiliondock.blk" - -INCLUDE "data/mapHeaders/celadonmansion5.asm" -INCLUDE "scripts/celadonmansion5.asm" -INCLUDE "data/mapObjects/celadonmansion5.asm" - -INCLUDE "data/mapHeaders/fuchsiamart.asm" -INCLUDE "scripts/fuchsiamart.asm" -INCLUDE "data/mapObjects/fuchsiamart.asm" -FuchsiaMartBlocks: INCBIN "maps/fuchsiamart.blk" - -INCLUDE "data/mapHeaders/saffronhouse1.asm" -INCLUDE "scripts/saffronhouse1.asm" -INCLUDE "data/mapObjects/saffronhouse1.asm" - -INCLUDE "data/mapHeaders/saffronhouse2.asm" -INCLUDE "scripts/saffronhouse2.asm" -INCLUDE "data/mapObjects/saffronhouse2.asm" - -INCLUDE "data/mapHeaders/diglettscaveroute2.asm" -INCLUDE "scripts/diglettscaveroute2.asm" -INCLUDE "data/mapObjects/diglettscaveroute2.asm" - -INCLUDE "data/mapHeaders/route2house.asm" -INCLUDE "scripts/route2house.asm" -INCLUDE "data/mapObjects/route2house.asm" - -INCLUDE "data/mapHeaders/route5gate.asm" -INCLUDE "scripts/route5gate.asm" -INCLUDE "data/mapObjects/route5gate.asm" -Route5GateBlocks: INCBIN "maps/route5gate.blk" - -INCLUDE "data/mapHeaders/route6gate.asm" -INCLUDE "scripts/route6gate.asm" -INCLUDE "data/mapObjects/route6gate.asm" -Route6GateBlocks: INCBIN "maps/route6gate.blk" - -INCLUDE "data/mapHeaders/route7gate.asm" -INCLUDE "scripts/route7gate.asm" -INCLUDE "data/mapObjects/route7gate.asm" -Route7GateBlocks: INCBIN "maps/route7gate.blk" - -INCLUDE "data/mapHeaders/route8gate.asm" -INCLUDE "scripts/route8gate.asm" -INCLUDE "data/mapObjects/route8gate.asm" -Route8GateBlocks: INCBIN "maps/route8gate.blk" - -INCLUDE "data/mapHeaders/undergroundpathentranceroute8.asm" -INCLUDE "scripts/undergroundpathentranceroute8.asm" -INCLUDE "data/mapObjects/undergroundpathentranceroute8.asm" - -INCLUDE "data/mapHeaders/powerplant.asm" -INCLUDE "scripts/powerplant.asm" -INCLUDE "data/mapObjects/powerplant.asm" -PowerPlantBlocks: INCBIN "maps/powerplant.blk" - -INCLUDE "data/mapHeaders/diglettscaveroute11.asm" -INCLUDE "scripts/diglettscaveroute11.asm" -INCLUDE "data/mapObjects/diglettscaveroute11.asm" - -INCLUDE "data/mapHeaders/route16house.asm" -INCLUDE "scripts/route16house.asm" -INCLUDE "data/mapObjects/route16house.asm" - -INCLUDE "data/mapHeaders/route22gate.asm" -INCLUDE "scripts/route22gate.asm" -INCLUDE "data/mapObjects/route22gate.asm" -Route22GateBlocks: INCBIN "maps/route22gate.blk" - -INCLUDE "data/mapHeaders/billshouse.asm" -INCLUDE "scripts/billshouse.asm" -INCLUDE "data/mapObjects/billshouse.asm" -BillsHouseBlocks: INCBIN "maps/billshouse.blk" -IF DEF(_OPTION_BEACH_HOUSE) -INCLUDE "data/mapHeaders/beach_house.asm" -INCLUDE "scripts/beach_house.asm" -BeachHouseBlockdata: INCBIN "maps/beach_house.blk" -INCLUDE "data/mapObjects/beach_house.asm" -ENDC - -INCLUDE "engine/menu/oaks_pc.asm" - -INCLUDE "engine/hidden_object_functions7.asm" - - -SECTION "Pics 1", ROMX, BANK[PICS_1] - -RhydonPicFront:: INCBIN "pic/bmon/rhydon.pic" -RhydonPicBack:: INCBIN "pic/monback/rhydonb.pic" -KangaskhanPicFront:: INCBIN "pic/bmon/kangaskhan.pic" -KangaskhanPicBack:: INCBIN "pic/monback/kangaskhanb.pic" -NidoranMPicFront:: INCBIN "pic/bmon/nidoranm.pic" -NidoranMPicBack:: INCBIN "pic/monback/nidoranmb.pic" -ClefairyPicFront:: INCBIN "pic/bmon/clefairy.pic" -ClefairyPicBack:: INCBIN "pic/monback/clefairyb.pic" -SpearowPicFront:: INCBIN "pic/bmon/spearow.pic" -SpearowPicBack:: INCBIN "pic/monback/spearowb.pic" -VoltorbPicFront:: INCBIN "pic/bmon/voltorb.pic" -VoltorbPicBack:: INCBIN "pic/monback/voltorbb.pic" -NidokingPicFront:: INCBIN "pic/bmon/nidoking.pic" -NidokingPicBack:: INCBIN "pic/monback/nidokingb.pic" -SlowbroPicFront:: INCBIN "pic/bmon/slowbro.pic" -SlowbroPicBack:: INCBIN "pic/monback/slowbrob.pic" -IvysaurPicFront:: INCBIN "pic/bmon/ivysaur.pic" -IvysaurPicBack:: INCBIN "pic/monback/ivysaurb.pic" -ExeggutorPicFront:: INCBIN "pic/bmon/exeggutor.pic" -ExeggutorPicBack:: INCBIN "pic/monback/exeggutorb.pic" -LickitungPicFront:: INCBIN "pic/bmon/lickitung.pic" -LickitungPicBack:: INCBIN "pic/monback/lickitungb.pic" -ExeggcutePicFront:: INCBIN "pic/bmon/exeggcute.pic" -ExeggcutePicBack:: INCBIN "pic/monback/exeggcuteb.pic" -GrimerPicFront:: INCBIN "pic/bmon/grimer.pic" -GrimerPicBack:: INCBIN "pic/monback/grimerb.pic" -GengarPicFront:: INCBIN "pic/bmon/gengar.pic" -GengarPicBack:: INCBIN "pic/monback/gengarb.pic" -NidoranFPicFront:: INCBIN "pic/bmon/nidoranf.pic" -NidoranFPicBack:: INCBIN "pic/monback/nidoranfb.pic" -NidoqueenPicFront:: INCBIN "pic/bmon/nidoqueen.pic" -NidoqueenPicBack:: INCBIN "pic/monback/nidoqueenb.pic" -CubonePicFront:: INCBIN "pic/bmon/cubone.pic" -CubonePicBack:: INCBIN "pic/monback/cuboneb.pic" -RhyhornPicFront:: INCBIN "pic/bmon/rhyhorn.pic" -RhyhornPicBack:: INCBIN "pic/monback/rhyhornb.pic" -LaprasPicFront:: INCBIN "pic/bmon/lapras.pic" -LaprasPicBack:: INCBIN "pic/monback/laprasb.pic" -ArcaninePicFront:: INCBIN "pic/bmon/arcanine.pic" -ArcaninePicBack:: INCBIN "pic/monback/arcanineb.pic" -GyaradosPicFront:: INCBIN "pic/bmon/gyarados.pic" -GyaradosPicBack:: INCBIN "pic/monback/gyaradosb.pic" -ShellderPicFront:: INCBIN "pic/bmon/shellder.pic" -ShellderPicBack:: INCBIN "pic/monback/shellderb.pic" -TentacoolPicFront:: INCBIN "pic/bmon/tentacool.pic" -TentacoolPicBack:: INCBIN "pic/monback/tentacoolb.pic" -GastlyPicFront:: INCBIN "pic/bmon/gastly.pic" -GastlyPicBack:: INCBIN "pic/monback/gastlyb.pic" -ScytherPicFront:: INCBIN "pic/bmon/scyther.pic" -ScytherPicBack:: INCBIN "pic/monback/scytherb.pic" -StaryuPicFront:: INCBIN "pic/bmon/staryu.pic" -StaryuPicBack:: INCBIN "pic/monback/staryub.pic" -BlastoisePicFront:: INCBIN "pic/bmon/blastoise.pic" -BlastoisePicBack:: INCBIN "pic/monback/blastoiseb.pic" -PinsirPicFront:: INCBIN "pic/bmon/pinsir.pic" -PinsirPicBack:: INCBIN "pic/monback/pinsirb.pic" -TangelaPicFront:: INCBIN "pic/bmon/tangela.pic" -TangelaPicBack:: INCBIN "pic/monback/tangelab.pic" - - -SECTION "Battle (bank 9)", ROMX, BANK[$9] -INCLUDE "engine/battle/print_type.asm" -INCLUDE "engine/battle/save_trainer_name.asm" -INCLUDE "engine/battle/moveEffects/focus_energy_effect.asm" - - -SECTION "Pics 2", ROMX, BANK[PICS_2] - -GrowlithePicFront:: INCBIN "pic/bmon/growlithe.pic" -GrowlithePicBack:: INCBIN "pic/monback/growlitheb.pic" -OnixPicFront:: INCBIN "pic/bmon/onix.pic" -OnixPicBack:: INCBIN "pic/monback/onixb.pic" -FearowPicFront:: INCBIN "pic/bmon/fearow.pic" -FearowPicBack:: INCBIN "pic/monback/fearowb.pic" -PidgeyPicFront:: INCBIN "pic/bmon/pidgey.pic" -PidgeyPicBack:: INCBIN "pic/monback/pidgeyb.pic" -SlowpokePicFront:: INCBIN "pic/bmon/slowpoke.pic" -SlowpokePicBack:: INCBIN "pic/monback/slowpokeb.pic" -KadabraPicFront:: INCBIN "pic/bmon/kadabra.pic" -KadabraPicBack:: INCBIN "pic/monback/kadabrab.pic" -GravelerPicFront:: INCBIN "pic/bmon/graveler.pic" -GravelerPicBack:: INCBIN "pic/monback/gravelerb.pic" -ChanseyPicFront:: INCBIN "pic/bmon/chansey.pic" -ChanseyPicBack:: INCBIN "pic/monback/chanseyb.pic" -MachokePicFront:: INCBIN "pic/bmon/machoke.pic" -MachokePicBack:: INCBIN "pic/monback/machokeb.pic" -MrMimePicFront:: INCBIN "pic/bmon/mr.mime.pic" -MrMimePicBack:: INCBIN "pic/monback/mr.mimeb.pic" -HitmonleePicFront:: INCBIN "pic/bmon/hitmonlee.pic" -HitmonleePicBack:: INCBIN "pic/monback/hitmonleeb.pic" -HitmonchanPicFront:: INCBIN "pic/bmon/hitmonchan.pic" -HitmonchanPicBack:: INCBIN "pic/monback/hitmonchanb.pic" -ArbokPicFront:: INCBIN "pic/bmon/arbok.pic" -ArbokPicBack:: INCBIN "pic/monback/arbokb.pic" -ParasectPicFront:: INCBIN "pic/bmon/parasect.pic" -ParasectPicBack:: INCBIN "pic/monback/parasectb.pic" -PsyduckPicFront:: INCBIN "pic/bmon/psyduck.pic" -PsyduckPicBack:: INCBIN "pic/monback/psyduckb.pic" -DrowzeePicFront:: INCBIN "pic/bmon/drowzee.pic" -DrowzeePicBack:: INCBIN "pic/monback/drowzeeb.pic" -GolemPicFront:: INCBIN "pic/bmon/golem.pic" -GolemPicBack:: INCBIN "pic/monback/golemb.pic" -MagmarPicFront:: INCBIN "pic/bmon/magmar.pic" -MagmarPicBack:: INCBIN "pic/monback/magmarb.pic" -ElectabuzzPicFront:: INCBIN "pic/bmon/electabuzz.pic" -ElectabuzzPicBack:: INCBIN "pic/monback/electabuzzb.pic" -MagnetonPicFront:: INCBIN "pic/bmon/magneton.pic" -MagnetonPicBack:: INCBIN "pic/monback/magnetonb.pic" -KoffingPicFront:: INCBIN "pic/bmon/koffing.pic" -KoffingPicBack:: INCBIN "pic/monback/koffingb.pic" -MankeyPicFront:: INCBIN "pic/bmon/mankey.pic" -MankeyPicBack:: INCBIN "pic/monback/mankeyb.pic" -SeelPicFront:: INCBIN "pic/bmon/seel.pic" -SeelPicBack:: INCBIN "pic/monback/seelb.pic" -DiglettPicFront:: INCBIN "pic/bmon/diglett.pic" -DiglettPicBack:: INCBIN "pic/monback/diglettb.pic" -TaurosPicFront:: INCBIN "pic/bmon/tauros.pic" -TaurosPicBack:: INCBIN "pic/monback/taurosb.pic" -FarfetchdPicFront:: INCBIN "pic/bmon/farfetchd.pic" -FarfetchdPicBack:: INCBIN "pic/monback/farfetchdb.pic" -VenonatPicFront:: INCBIN "pic/bmon/venonat.pic" -VenonatPicBack:: INCBIN "pic/monback/venonatb.pic" -DragonitePicFront:: INCBIN "pic/bmon/dragonite.pic" -DragonitePicBack:: INCBIN "pic/monback/dragoniteb.pic" -DoduoPicFront:: INCBIN "pic/bmon/doduo.pic" -DoduoPicBack:: INCBIN "pic/monback/doduob.pic" -PoliwagPicFront:: INCBIN "pic/bmon/poliwag.pic" -PoliwagPicBack:: INCBIN "pic/monback/poliwagb.pic" -JynxPicFront:: INCBIN "pic/bmon/jynx.pic" -JynxPicBack:: INCBIN "pic/monback/jynxb.pic" -MoltresPicFront:: INCBIN "pic/bmon/moltres.pic" -MoltresPicBack:: INCBIN "pic/monback/moltresb.pic" - - -SECTION "Battle (bank A)", ROMX, BANK[$A] -INCLUDE "engine/battle/moveEffects/leech_seed_effect.asm" - - -SECTION "Pics 3", ROMX, BANK[PICS_3] - -ArticunoPicFront:: INCBIN "pic/bmon/articuno.pic" -ArticunoPicBack:: INCBIN "pic/monback/articunob.pic" -ZapdosPicFront:: INCBIN "pic/bmon/zapdos.pic" -ZapdosPicBack:: INCBIN "pic/monback/zapdosb.pic" -DittoPicFront:: INCBIN "pic/bmon/ditto.pic" -DittoPicBack:: INCBIN "pic/monback/dittob.pic" -MeowthPicFront:: INCBIN "pic/bmon/meowth.pic" -MeowthPicBack:: INCBIN "pic/monback/meowthb.pic" -KrabbyPicFront:: INCBIN "pic/bmon/krabby.pic" -KrabbyPicBack:: INCBIN "pic/monback/krabbyb.pic" -VulpixPicFront:: INCBIN "pic/bmon/vulpix.pic" -VulpixPicBack:: INCBIN "pic/monback/vulpixb.pic" -NinetalesPicFront:: INCBIN "pic/bmon/ninetales.pic" -NinetalesPicBack:: INCBIN "pic/monback/ninetalesb.pic" -PikachuPicFront:: INCBIN "pic/bmon/pikachu.pic" -PikachuPicBack:: INCBIN "pic/monback/pikachub.pic" -RaichuPicFront:: INCBIN "pic/bmon/raichu.pic" -RaichuPicBack:: INCBIN "pic/monback/raichub.pic" -DratiniPicFront:: INCBIN "pic/bmon/dratini.pic" -DratiniPicBack:: INCBIN "pic/monback/dratinib.pic" -DragonairPicFront:: INCBIN "pic/bmon/dragonair.pic" -DragonairPicBack:: INCBIN "pic/monback/dragonairb.pic" -KabutoPicFront:: INCBIN "pic/bmon/kabuto.pic" -KabutoPicBack:: INCBIN "pic/monback/kabutob.pic" -KabutopsPicFront:: INCBIN "pic/bmon/kabutops.pic" -KabutopsPicBack:: INCBIN "pic/monback/kabutopsb.pic" -HorseaPicFront:: INCBIN "pic/bmon/horsea.pic" -HorseaPicBack:: INCBIN "pic/monback/horseab.pic" -SeadraPicFront:: INCBIN "pic/bmon/seadra.pic" -SeadraPicBack:: INCBIN "pic/monback/seadrab.pic" -SandshrewPicFront:: INCBIN "pic/bmon/sandshrew.pic" -SandshrewPicBack:: INCBIN "pic/monback/sandshrewb.pic" -SandslashPicFront:: INCBIN "pic/bmon/sandslash.pic" -SandslashPicBack:: INCBIN "pic/monback/sandslashb.pic" -OmanytePicFront:: INCBIN "pic/bmon/omanyte.pic" -OmanytePicBack:: INCBIN "pic/monback/omanyteb.pic" -OmastarPicFront:: INCBIN "pic/bmon/omastar.pic" -OmastarPicBack:: INCBIN "pic/monback/omastarb.pic" -JigglypuffPicFront:: INCBIN "pic/bmon/jigglypuff.pic" -JigglypuffPicBack:: INCBIN "pic/monback/jigglypuffb.pic" -WigglytuffPicFront:: INCBIN "pic/bmon/wigglytuff.pic" -WigglytuffPicBack:: INCBIN "pic/monback/wigglytuffb.pic" -EeveePicFront:: INCBIN "pic/bmon/eevee.pic" -EeveePicBack:: INCBIN "pic/monback/eeveeb.pic" -FlareonPicFront:: INCBIN "pic/bmon/flareon.pic" -FlareonPicBack:: INCBIN "pic/monback/flareonb.pic" -JolteonPicFront:: INCBIN "pic/bmon/jolteon.pic" -JolteonPicBack:: INCBIN "pic/monback/jolteonb.pic" -VaporeonPicFront:: INCBIN "pic/bmon/vaporeon.pic" -VaporeonPicBack:: INCBIN "pic/monback/vaporeonb.pic" -MachopPicFront:: INCBIN "pic/bmon/machop.pic" -MachopPicBack:: INCBIN "pic/monback/machopb.pic" -ZubatPicFront:: INCBIN "pic/bmon/zubat.pic" -ZubatPicBack:: INCBIN "pic/monback/zubatb.pic" -EkansPicFront:: INCBIN "pic/bmon/ekans.pic" -EkansPicBack:: INCBIN "pic/monback/ekansb.pic" -ParasPicFront:: INCBIN "pic/bmon/paras.pic" -ParasPicBack:: INCBIN "pic/monback/parasb.pic" -PoliwhirlPicFront:: INCBIN "pic/bmon/poliwhirl.pic" -PoliwhirlPicBack:: INCBIN "pic/monback/poliwhirlb.pic" -PoliwrathPicFront:: INCBIN "pic/bmon/poliwrath.pic" -PoliwrathPicBack:: INCBIN "pic/monback/poliwrathb.pic" -WeedlePicFront:: INCBIN "pic/bmon/weedle.pic" -WeedlePicBack:: INCBIN "pic/monback/weedleb.pic" -KakunaPicFront:: INCBIN "pic/bmon/kakuna.pic" -KakunaPicBack:: INCBIN "pic/monback/kakunab.pic" -BeedrillPicFront:: INCBIN "pic/bmon/beedrill.pic" -BeedrillPicBack:: INCBIN "pic/monback/beedrillb.pic" - -FossilKabutopsPic:: INCBIN "pic/bmon/fossilkabutops.pic" - - -SECTION "Battle (bank B)", ROMX, BANK[$B] - -INCLUDE "engine/battle/display_effectiveness.asm" - -TrainerInfoTextBoxTileGraphics: INCBIN "gfx/trainer_info.2bpp" -BlankLeaderNames: INCBIN "gfx/blank_leader_names.2bpp" -CircleTile: INCBIN "gfx/circle_tile.2bpp" -BadgeNumbersTileGraphics: INCBIN "gfx/badge_numbers.2bpp" - -INCLUDE "engine/items/tmhm.asm" -INCLUDE "engine/battle/scale_sprites.asm" -INCLUDE "engine/battle/moveEffects/pay_day_effect.asm" -INCLUDE "engine/game_corner_slots2.asm" - - -SECTION "Pics 4", ROMX, BANK[PICS_4] - -DodrioPicFront:: INCBIN "pic/bmon/dodrio.pic" -DodrioPicBack:: INCBIN "pic/monback/dodriob.pic" -PrimeapePicFront:: INCBIN "pic/bmon/primeape.pic" -PrimeapePicBack:: INCBIN "pic/monback/primeapeb.pic" -DugtrioPicFront:: INCBIN "pic/bmon/dugtrio.pic" -DugtrioPicBack:: INCBIN "pic/monback/dugtriob.pic" -VenomothPicFront:: INCBIN "pic/bmon/venomoth.pic" -VenomothPicBack:: INCBIN "pic/monback/venomothb.pic" -DewgongPicFront:: INCBIN "pic/bmon/dewgong.pic" -DewgongPicBack:: INCBIN "pic/monback/dewgongb.pic" -CaterpiePicFront:: INCBIN "pic/bmon/caterpie.pic" -CaterpiePicBack:: INCBIN "pic/monback/caterpieb.pic" -MetapodPicFront:: INCBIN "pic/bmon/metapod.pic" -MetapodPicBack:: INCBIN "pic/monback/metapodb.pic" -ButterfreePicFront:: INCBIN "pic/bmon/butterfree.pic" -ButterfreePicBack:: INCBIN "pic/monback/butterfreeb.pic" -MachampPicFront:: INCBIN "pic/bmon/machamp.pic" -MachampPicBack:: INCBIN "pic/monback/machampb.pic" -GolduckPicFront:: INCBIN "pic/bmon/golduck.pic" -GolduckPicBack:: INCBIN "pic/monback/golduckb.pic" -HypnoPicFront:: INCBIN "pic/bmon/hypno.pic" -HypnoPicBack:: INCBIN "pic/monback/hypnob.pic" -GolbatPicFront:: INCBIN "pic/bmon/golbat.pic" -GolbatPicBack:: INCBIN "pic/monback/golbatb.pic" -MewtwoPicFront:: INCBIN "pic/bmon/mewtwo.pic" -MewtwoPicBack:: INCBIN "pic/monback/mewtwob.pic" -SnorlaxPicFront:: INCBIN "pic/bmon/snorlax.pic" -SnorlaxPicBack:: INCBIN "pic/monback/snorlaxb.pic" -MagikarpPicFront:: INCBIN "pic/bmon/magikarp.pic" -MagikarpPicBack:: INCBIN "pic/monback/magikarpb.pic" -MukPicFront:: INCBIN "pic/bmon/muk.pic" -MukPicBack:: INCBIN "pic/monback/mukb.pic" -KinglerPicFront:: INCBIN "pic/bmon/kingler.pic" -KinglerPicBack:: INCBIN "pic/monback/kinglerb.pic" -CloysterPicFront:: INCBIN "pic/bmon/cloyster.pic" -CloysterPicBack:: INCBIN "pic/monback/cloysterb.pic" -ElectrodePicFront:: INCBIN "pic/bmon/electrode.pic" -ElectrodePicBack:: INCBIN "pic/monback/electrodeb.pic" -ClefablePicFront:: INCBIN "pic/bmon/clefable.pic" -ClefablePicBack:: INCBIN "pic/monback/clefableb.pic" -WeezingPicFront:: INCBIN "pic/bmon/weezing.pic" -WeezingPicBack:: INCBIN "pic/monback/weezingb.pic" -PersianPicFront:: INCBIN "pic/bmon/persian.pic" -PersianPicBack:: INCBIN "pic/monback/persianb.pic" -MarowakPicFront:: INCBIN "pic/bmon/marowak.pic" -MarowakPicBack:: INCBIN "pic/monback/marowakb.pic" -HaunterPicFront:: INCBIN "pic/bmon/haunter.pic" -HaunterPicBack:: INCBIN "pic/monback/haunterb.pic" -AbraPicFront:: INCBIN "pic/bmon/abra.pic" -AbraPicBack:: INCBIN "pic/monback/abrab.pic" -AlakazamPicFront:: INCBIN "pic/bmon/alakazam.pic" -AlakazamPicBack:: INCBIN "pic/monback/alakazamb.pic" -PidgeottoPicFront:: INCBIN "pic/bmon/pidgeotto.pic" -PidgeottoPicBack:: INCBIN "pic/monback/pidgeottob.pic" -PidgeotPicFront:: INCBIN "pic/bmon/pidgeot.pic" -PidgeotPicBack:: INCBIN "pic/monback/pidgeotb.pic" -StarmiePicFront:: INCBIN "pic/bmon/starmie.pic" -StarmiePicBack:: INCBIN "pic/monback/starmieb.pic" - -RedPicBack:: INCBIN "pic/trainer/redb.pic" -OldManPic:: INCBIN "pic/trainer/oldman.pic" - - -SECTION "Battle (bank C)", ROMX, BANK[$C] -INCLUDE "engine/battle/moveEffects/mist_effect.asm" -INCLUDE "engine/battle/moveEffects/one_hit_ko_effect.asm" - - -SECTION "Pics 5", ROMX, BANK[PICS_5] - -BulbasaurPicFront:: INCBIN "pic/bmon/bulbasaur.pic" -BulbasaurPicBack:: INCBIN "pic/monback/bulbasaurb.pic" -VenusaurPicFront:: INCBIN "pic/bmon/venusaur.pic" -VenusaurPicBack:: INCBIN "pic/monback/venusaurb.pic" -TentacruelPicFront:: INCBIN "pic/bmon/tentacruel.pic" -TentacruelPicBack:: INCBIN "pic/monback/tentacruelb.pic" -GoldeenPicFront:: INCBIN "pic/bmon/goldeen.pic" -GoldeenPicBack:: INCBIN "pic/monback/goldeenb.pic" -SeakingPicFront:: INCBIN "pic/bmon/seaking.pic" -SeakingPicBack:: INCBIN "pic/monback/seakingb.pic" -PonytaPicFront:: INCBIN "pic/bmon/ponyta.pic" -RapidashPicFront:: INCBIN "pic/bmon/rapidash.pic" -PonytaPicBack:: INCBIN "pic/monback/ponytab.pic" -RapidashPicBack:: INCBIN "pic/monback/rapidashb.pic" -RattataPicFront:: INCBIN "pic/bmon/rattata.pic" -RattataPicBack:: INCBIN "pic/monback/rattatab.pic" -RaticatePicFront:: INCBIN "pic/bmon/raticate.pic" -RaticatePicBack:: INCBIN "pic/monback/raticateb.pic" -NidorinoPicFront:: INCBIN "pic/bmon/nidorino.pic" -NidorinoPicBack:: INCBIN "pic/monback/nidorinob.pic" -NidorinaPicFront:: INCBIN "pic/bmon/nidorina.pic" -NidorinaPicBack:: INCBIN "pic/monback/nidorinab.pic" -GeodudePicFront:: INCBIN "pic/bmon/geodude.pic" -GeodudePicBack:: INCBIN "pic/monback/geodudeb.pic" -PorygonPicFront:: INCBIN "pic/bmon/porygon.pic" -PorygonPicBack:: INCBIN "pic/monback/porygonb.pic" -AerodactylPicFront:: INCBIN "pic/bmon/aerodactyl.pic" -AerodactylPicBack:: INCBIN "pic/monback/aerodactylb.pic" -MagnemitePicFront:: INCBIN "pic/bmon/magnemite.pic" -MagnemitePicBack:: INCBIN "pic/monback/magnemiteb.pic" -CharmanderPicFront:: INCBIN "pic/bmon/charmander.pic" -CharmanderPicBack:: INCBIN "pic/monback/charmanderb.pic" -SquirtlePicFront:: INCBIN "pic/bmon/squirtle.pic" -SquirtlePicBack:: INCBIN "pic/monback/squirtleb.pic" -CharmeleonPicFront:: INCBIN "pic/bmon/charmeleon.pic" -CharmeleonPicBack:: INCBIN "pic/monback/charmeleonb.pic" -WartortlePicFront:: INCBIN "pic/bmon/wartortle.pic" -WartortlePicBack:: INCBIN "pic/monback/wartortleb.pic" -CharizardPicFront:: INCBIN "pic/bmon/charizard.pic" -CharizardPicBack:: INCBIN "pic/monback/charizardb.pic" -FossilAerodactylPic:: INCBIN "pic/bmon/fossilaerodactyl.pic" -GhostPic:: INCBIN "pic/other/ghost.pic" -OddishPicFront:: INCBIN "pic/bmon/oddish.pic" -OddishPicBack:: INCBIN "pic/monback/oddishb.pic" -GloomPicFront:: INCBIN "pic/bmon/gloom.pic" -GloomPicBack:: INCBIN "pic/monback/gloomb.pic" -VileplumePicFront:: INCBIN "pic/bmon/vileplume.pic" -VileplumePicBack:: INCBIN "pic/monback/vileplumeb.pic" -BellsproutPicFront:: INCBIN "pic/bmon/bellsprout.pic" -BellsproutPicBack:: INCBIN "pic/monback/bellsproutb.pic" -WeepinbellPicFront:: INCBIN "pic/bmon/weepinbell.pic" -WeepinbellPicBack:: INCBIN "pic/monback/weepinbellb.pic" -VictreebelPicFront:: INCBIN "pic/bmon/victreebel.pic" -VictreebelPicBack:: INCBIN "pic/monback/victreebelb.pic" - - -SECTION "Battle (bank D)", ROMX, BANK[$D] - -INCLUDE "engine/titlescreen2.asm" -INCLUDE "engine/battle/link_battle_versus_text.asm" -INCLUDE "engine/slot_machine.asm" -INCLUDE "engine/overworld/pewter_guys.asm" -INCLUDE "engine/multiply_divide.asm" -INCLUDE "engine/game_corner_slots.asm" - - -SECTION "bankE",ROMX,BANK[$E] - -INCLUDE "data/moves.asm" -BaseStats: INCLUDE "data/base_stats.asm" -INCLUDE "data/cries.asm" -INCLUDE "engine/battle/unused_stats_functions.asm" -INCLUDE "engine/battle/scroll_draw_trainer_pic.asm" -INCLUDE "engine/battle/trainer_ai.asm" -INCLUDE "engine/battle/draw_hud_pokeball_gfx.asm" - -TradingAnimationGraphics: - INCBIN "gfx/game_boy.norepeat.2bpp" - INCBIN "gfx/link_cable.2bpp" - -TradingAnimationGraphics2: -; Pokeball traveling through the link cable. - INCBIN "gfx/trade2.2bpp" - -INCLUDE "engine/evos_moves.asm" -INCLUDE "engine/battle/moveEffects/heal_effect.asm" -INCLUDE "engine/battle/moveEffects/transform_effect.asm" -INCLUDE "engine/battle/moveEffects/reflect_light_screen_effect.asm" - - -SECTION "bankF",ROMX,BANK[$F] - -INCLUDE "engine/battle/core.asm" - - -SECTION "bank10",ROMX,BANK[$10] - -INCLUDE "engine/menu/pokedex.asm" -INCLUDE "engine/trade.asm" -INCLUDE "engine/intro.asm" -INCLUDE "engine/trade2.asm" - - -SECTION "bank11",ROMX,BANK[$11] - -INCLUDE "data/mapHeaders/lavendertown.asm" -INCLUDE "data/mapObjects/lavendertown.asm" -LavenderTownBlocks: INCBIN "maps/lavendertown.blk" - -ViridianPokecenterBlocks: INCBIN "maps/viridianpokecenter.blk" - -SafariZoneRestHouse1Blocks: -SafariZoneRestHouse2Blocks: -SafariZoneRestHouse3Blocks: -SafariZoneRestHouse4Blocks: INCBIN "maps/safarizoneresthouse1.blk" - -INCLUDE "scripts/lavendertown.asm" - -INCLUDE "engine/pokedex_rating.asm" - -INCLUDE "data/mapHeaders/viridianpokecenter.asm" -INCLUDE "scripts/viridianpokecenter.asm" -INCLUDE "data/mapObjects/viridianpokecenter.asm" - -INCLUDE "data/mapHeaders/mansion1.asm" -INCLUDE "scripts/mansion1.asm" -INCLUDE "data/mapObjects/mansion1.asm" -Mansion1Blocks: INCBIN "maps/mansion1.blk" - -INCLUDE "data/mapHeaders/rocktunnel1.asm" -INCLUDE "scripts/rocktunnel1.asm" -INCLUDE "data/mapObjects/rocktunnel1.asm" -RockTunnel1Blocks: INCBIN "maps/rocktunnel1.blk" - -INCLUDE "data/mapHeaders/seafoamislands1.asm" -INCLUDE "scripts/seafoamislands1.asm" -INCLUDE "data/mapObjects/seafoamislands1.asm" -SeafoamIslands1Blocks: INCBIN "maps/seafoamislands1.blk" - -INCLUDE "data/mapHeaders/ssanne3.asm" -INCLUDE "scripts/ssanne3.asm" -INCLUDE "data/mapObjects/ssanne3.asm" -SSAnne3Blocks: INCBIN "maps/ssanne3.blk" - -INCLUDE "data/mapHeaders/victoryroad3.asm" -INCLUDE "scripts/victoryroad3.asm" -INCLUDE "data/mapObjects/victoryroad3.asm" -VictoryRoad3Blocks: INCBIN "maps/victoryroad3.blk" - -INCLUDE "data/mapHeaders/rockethideout1.asm" -INCLUDE "scripts/rockethideout1.asm" -INCLUDE "data/mapObjects/rockethideout1.asm" -RocketHideout1Blocks: INCBIN "maps/rockethideout1.blk" - -INCLUDE "data/mapHeaders/rockethideout2.asm" -INCLUDE "scripts/rockethideout2.asm" -INCLUDE "data/mapObjects/rockethideout2.asm" -RocketHideout2Blocks: INCBIN "maps/rockethideout2.blk" - -INCLUDE "data/mapHeaders/rockethideout3.asm" -INCLUDE "scripts/rockethideout3.asm" -INCLUDE "data/mapObjects/rockethideout3.asm" -RocketHideout3Blocks: INCBIN "maps/rockethideout3.blk" - -INCLUDE "data/mapHeaders/rockethideout4.asm" -INCLUDE "scripts/rockethideout4.asm" -INCLUDE "data/mapObjects/rockethideout4.asm" -RocketHideout4Blocks: INCBIN "maps/rockethideout4.blk" - -INCLUDE "data/mapHeaders/rockethideoutelevator.asm" -INCLUDE "scripts/rockethideoutelevator.asm" -INCLUDE "data/mapObjects/rockethideoutelevator.asm" -RocketHideoutElevatorBlocks: INCBIN "maps/rockethideoutelevator.blk" - -INCLUDE "data/mapHeaders/silphcoelevator.asm" -INCLUDE "scripts/silphcoelevator.asm" -INCLUDE "data/mapObjects/silphcoelevator.asm" -SilphCoElevatorBlocks: INCBIN "maps/silphcoelevator.blk" - -INCLUDE "data/mapHeaders/safarizoneeast.asm" -INCLUDE "scripts/safarizoneeast.asm" -INCLUDE "data/mapObjects/safarizoneeast.asm" -SafariZoneEastBlocks: INCBIN "maps/safarizoneeast.blk" - -INCLUDE "data/mapHeaders/safarizonenorth.asm" -INCLUDE "scripts/safarizonenorth.asm" -INCLUDE "data/mapObjects/safarizonenorth.asm" -SafariZoneNorthBlocks: INCBIN "maps/safarizonenorth.blk" - -INCLUDE "data/mapHeaders/safarizonecenter.asm" -INCLUDE "scripts/safarizonecenter.asm" -INCLUDE "data/mapObjects/safarizonecenter.asm" -SafariZoneCenterBlocks: INCBIN "maps/safarizonecenter.blk" - -INCLUDE "data/mapHeaders/safarizoneresthouse1.asm" -INCLUDE "scripts/safarizoneresthouse1.asm" -INCLUDE "data/mapObjects/safarizoneresthouse1.asm" - -INCLUDE "data/mapHeaders/safarizoneresthouse2.asm" -INCLUDE "scripts/safarizoneresthouse2.asm" -INCLUDE "data/mapObjects/safarizoneresthouse2.asm" - -INCLUDE "data/mapHeaders/safarizoneresthouse3.asm" -INCLUDE "scripts/safarizoneresthouse3.asm" -INCLUDE "data/mapObjects/safarizoneresthouse3.asm" - -INCLUDE "data/mapHeaders/safarizoneresthouse4.asm" -INCLUDE "scripts/safarizoneresthouse4.asm" -INCLUDE "data/mapObjects/safarizoneresthouse4.asm" - -INCLUDE "data/mapHeaders/unknowndungeon2.asm" -INCLUDE "scripts/unknowndungeon2.asm" -INCLUDE "data/mapObjects/unknowndungeon2.asm" -UnknownDungeon2Blocks: INCBIN "maps/unknowndungeon2.blk" - -INCLUDE "data/mapHeaders/unknowndungeon3.asm" -INCLUDE "scripts/unknowndungeon3.asm" -INCLUDE "data/mapObjects/unknowndungeon3.asm" -UnknownDungeon3Blocks: INCBIN "maps/unknowndungeon3.blk" - -INCLUDE "data/mapHeaders/rocktunnel2.asm" -INCLUDE "scripts/rocktunnel2.asm" -INCLUDE "data/mapObjects/rocktunnel2.asm" -RockTunnel2Blocks: INCBIN "maps/rocktunnel2.blk" - -INCLUDE "data/mapHeaders/seafoamislands2.asm" -INCLUDE "scripts/seafoamislands2.asm" -INCLUDE "data/mapObjects/seafoamislands2.asm" -SeafoamIslands2Blocks: INCBIN "maps/seafoamislands2.blk" - -INCLUDE "data/mapHeaders/seafoamislands3.asm" -INCLUDE "scripts/seafoamislands3.asm" -INCLUDE "data/mapObjects/seafoamislands3.asm" -SeafoamIslands3Blocks: INCBIN "maps/seafoamislands3.blk" - -INCLUDE "data/mapHeaders/seafoamislands4.asm" -INCLUDE "scripts/seafoamislands4.asm" -INCLUDE "data/mapObjects/seafoamislands4.asm" -SeafoamIslands4Blocks: INCBIN "maps/seafoamislands4.blk" - -INCLUDE "data/mapHeaders/seafoamislands5.asm" -INCLUDE "scripts/seafoamislands5.asm" -INCLUDE "data/mapObjects/seafoamislands5.asm" -SeafoamIslands5Blocks: INCBIN "maps/seafoamislands5.blk" - -INCLUDE "engine/overworld/hidden_objects.asm" - - -SECTION "bank12",ROMX,BANK[$12] - -INCLUDE "data/mapHeaders/route7.asm" -INCLUDE "data/mapObjects/route7.asm" -Route7Blocks: INCBIN "maps/route7.blk" - -CeladonPokecenterBlocks: -RockTunnelPokecenterBlocks: -MtMoonPokecenterBlocks: INCBIN "maps/mtmoonpokecenter.blk" - -Route18GateBlocks: -Route15GateBlocks: -Route11GateBlocks: INCBIN "maps/route11gate.blk" - -Route18GateUpstairsBlocks: -Route16GateUpstairsBlocks: -Route12GateUpstairsBlocks: -Route15GateUpstairsBlocks: -Route11GateUpstairsBlocks: INCBIN "maps/route11gateupstairs.blk" - -INCLUDE "engine/predefs12.asm" - -INCLUDE "scripts/route7.asm" - -INCLUDE "data/mapHeaders/redshouse1f.asm" -INCLUDE "scripts/redshouse1f.asm" -INCLUDE "data/mapObjects/redshouse1f.asm" -RedsHouse1FBlocks: INCBIN "maps/redshouse1f.blk" - -INCLUDE "data/mapHeaders/celadonmart3.asm" -INCLUDE "scripts/celadonmart3.asm" -INCLUDE "data/mapObjects/celadonmart3.asm" -CeladonMart3Blocks: INCBIN "maps/celadonmart3.blk" - -INCLUDE "data/mapHeaders/celadonmart4.asm" -INCLUDE "scripts/celadonmart4.asm" -INCLUDE "data/mapObjects/celadonmart4.asm" -CeladonMart4Blocks: INCBIN "maps/celadonmart4.blk" - -INCLUDE "data/mapHeaders/celadonmartroof.asm" -INCLUDE "scripts/celadonmartroof.asm" -INCLUDE "data/mapObjects/celadonmartroof.asm" -CeladonMartRoofBlocks: INCBIN "maps/celadonmartroof.blk" - -INCLUDE "data/mapHeaders/celadonmartelevator.asm" -INCLUDE "scripts/celadonmartelevator.asm" -INCLUDE "data/mapObjects/celadonmartelevator.asm" -CeladonMartElevatorBlocks: INCBIN "maps/celadonmartelevator.blk" - -INCLUDE "data/mapHeaders/celadonmansion1.asm" -INCLUDE "scripts/celadonmansion1.asm" -INCLUDE "data/mapObjects/celadonmansion1.asm" -CeladonMansion1Blocks: INCBIN "maps/celadonmansion1.blk" - -INCLUDE "data/mapHeaders/celadonmansion2.asm" -INCLUDE "scripts/celadonmansion2.asm" -INCLUDE "data/mapObjects/celadonmansion2.asm" -CeladonMansion2Blocks: INCBIN "maps/celadonmansion2.blk" - -INCLUDE "data/mapHeaders/celadonmansion3.asm" -INCLUDE "scripts/celadonmansion3.asm" -INCLUDE "data/mapObjects/celadonmansion3.asm" -CeladonMansion3Blocks: INCBIN "maps/celadonmansion3.blk" - -INCLUDE "data/mapHeaders/celadonmansion4.asm" -INCLUDE "scripts/celadonmansion4.asm" -INCLUDE "data/mapObjects/celadonmansion4.asm" -CeladonMansion4Blocks: INCBIN "maps/celadonmansion4.blk" - -INCLUDE "data/mapHeaders/celadonpokecenter.asm" -INCLUDE "scripts/celadonpokecenter.asm" -INCLUDE "data/mapObjects/celadonpokecenter.asm" - -INCLUDE "data/mapHeaders/celadongym.asm" -INCLUDE "scripts/celadongym.asm" -INCLUDE "data/mapObjects/celadongym.asm" -CeladonGymBlocks: INCBIN "maps/celadongym.blk" - -INCLUDE "data/mapHeaders/celadongamecorner.asm" -INCLUDE "scripts/celadongamecorner.asm" -INCLUDE "data/mapObjects/celadongamecorner.asm" -CeladonGameCornerBlocks: INCBIN "maps/celadongamecorner.blk" - -INCLUDE "data/mapHeaders/celadonmart5.asm" -INCLUDE "scripts/celadonmart5.asm" -INCLUDE "data/mapObjects/celadonmart5.asm" -CeladonMart5Blocks: INCBIN "maps/celadonmart5.blk" - -INCLUDE "data/mapHeaders/celadonprizeroom.asm" -INCLUDE "scripts/celadonprizeroom.asm" -INCLUDE "data/mapObjects/celadonprizeroom.asm" -CeladonPrizeRoomBlocks: INCBIN "maps/celadonprizeroom.blk" - -INCLUDE "data/mapHeaders/celadondiner.asm" -INCLUDE "scripts/celadondiner.asm" -INCLUDE "data/mapObjects/celadondiner.asm" -CeladonDinerBlocks: INCBIN "maps/celadondiner.blk" - -INCLUDE "data/mapHeaders/celadonhouse.asm" -INCLUDE "scripts/celadonhouse.asm" -INCLUDE "data/mapObjects/celadonhouse.asm" -CeladonHouseBlocks: INCBIN "maps/celadonhouse.blk" - -INCLUDE "data/mapHeaders/celadonhotel.asm" -INCLUDE "scripts/celadonhotel.asm" -INCLUDE "data/mapObjects/celadonhotel.asm" -CeladonHotelBlocks: INCBIN "maps/celadonhotel.blk" - -INCLUDE "data/mapHeaders/mtmoonpokecenter.asm" -INCLUDE "scripts/mtmoonpokecenter.asm" -INCLUDE "data/mapObjects/mtmoonpokecenter.asm" - -INCLUDE "data/mapHeaders/rocktunnelpokecenter.asm" -INCLUDE "scripts/rocktunnelpokecenter.asm" -INCLUDE "data/mapObjects/rocktunnelpokecenter.asm" - -INCLUDE "data/mapHeaders/route11gate.asm" -INCLUDE "scripts/route11gate.asm" -INCLUDE "data/mapObjects/route11gate.asm" - -INCLUDE "data/mapHeaders/route11gateupstairs.asm" -INCLUDE "scripts/route11gateupstairs.asm" -INCLUDE "data/mapObjects/route11gateupstairs.asm" - -INCLUDE "data/mapHeaders/route12gate.asm" -INCLUDE "scripts/route12gate.asm" -INCLUDE "data/mapObjects/route12gate.asm" -Route12GateBlocks: INCBIN "maps/route12gate.blk" - -INCLUDE "data/mapHeaders/route12gateupstairs.asm" -INCLUDE "scripts/route12gateupstairs.asm" -INCLUDE "data/mapObjects/route12gateupstairs.asm" - -INCLUDE "data/mapHeaders/route15gate.asm" -INCLUDE "scripts/route15gate.asm" -INCLUDE "data/mapObjects/route15gate.asm" - -INCLUDE "data/mapHeaders/route15gateupstairs.asm" -INCLUDE "scripts/route15gateupstairs.asm" -INCLUDE "data/mapObjects/route15gateupstairs.asm" - -INCLUDE "data/mapHeaders/route16gate.asm" -INCLUDE "scripts/route16gate.asm" -INCLUDE "data/mapObjects/route16gate.asm" -Route16GateBlocks: INCBIN "maps/route16gate.blk" - -INCLUDE "data/mapHeaders/route16gateupstairs.asm" -INCLUDE "scripts/route16gateupstairs.asm" -INCLUDE "data/mapObjects/route16gateupstairs.asm" - -INCLUDE "data/mapHeaders/route18gate.asm" -INCLUDE "scripts/route18gate.asm" -INCLUDE "data/mapObjects/route18gate.asm" - -INCLUDE "data/mapHeaders/route18gateupstairs.asm" -INCLUDE "scripts/route18gateupstairs.asm" -INCLUDE "data/mapObjects/route18gateupstairs.asm" - -INCLUDE "data/mapHeaders/mtmoon1.asm" -INCLUDE "scripts/mtmoon1.asm" -INCLUDE "data/mapObjects/mtmoon1.asm" -MtMoon1Blocks: INCBIN "maps/mtmoon1.blk" - -INCLUDE "data/mapHeaders/mtmoon3.asm" -INCLUDE "scripts/mtmoon3.asm" -INCLUDE "data/mapObjects/mtmoon3.asm" -MtMoon3Blocks: INCBIN "maps/mtmoon3.blk" - -INCLUDE "data/mapHeaders/safarizonewest.asm" -INCLUDE "scripts/safarizonewest.asm" -INCLUDE "data/mapObjects/safarizonewest.asm" -SafariZoneWestBlocks: INCBIN "maps/safarizonewest.blk" - -INCLUDE "data/mapHeaders/safarizonesecrethouse.asm" -INCLUDE "scripts/safarizonesecrethouse.asm" -INCLUDE "data/mapObjects/safarizonesecrethouse.asm" -SafariZoneSecretHouseBlocks: INCBIN "maps/safarizonesecrethouse.blk" - - -SECTION "bank13",ROMX,BANK[$13] - -TrainerPics:: -YoungsterPic:: INCBIN "pic/trainer/youngster.pic" -BugCatcherPic:: INCBIN "pic/trainer/bugcatcher.pic" -LassPic:: INCBIN "pic/trainer/lass.pic" -SailorPic:: INCBIN "pic/trainer/sailor.pic" -JrTrainerMPic:: INCBIN "pic/trainer/jr.trainerm.pic" -JrTrainerFPic:: INCBIN "pic/trainer/jr.trainerf.pic" -PokemaniacPic:: INCBIN "pic/trainer/pokemaniac.pic" -SuperNerdPic:: INCBIN "pic/trainer/supernerd.pic" -HikerPic:: INCBIN "pic/trainer/hiker.pic" -BikerPic:: INCBIN "pic/trainer/biker.pic" -BurglarPic:: INCBIN "pic/trainer/burglar.pic" -EngineerPic:: INCBIN "pic/trainer/engineer.pic" -FisherPic:: INCBIN "pic/trainer/fisher.pic" -SwimmerPic:: INCBIN "pic/trainer/swimmer.pic" -CueBallPic:: INCBIN "pic/trainer/cueball.pic" -GamblerPic:: INCBIN "pic/trainer/gambler.pic" -BeautyPic:: INCBIN "pic/trainer/beauty.pic" -PsychicPic:: INCBIN "pic/trainer/psychic.pic" -RockerPic:: INCBIN "pic/trainer/rocker.pic" -JugglerPic:: INCBIN "pic/trainer/juggler.pic" -TamerPic:: INCBIN "pic/trainer/tamer.pic" -BirdKeeperPic:: INCBIN "pic/trainer/birdkeeper.pic" -BlackbeltPic:: INCBIN "pic/trainer/blackbelt.pic" -Rival1Pic:: INCBIN "pic/trainer/rival1.pic" -ProfOakPic:: INCBIN "pic/trainer/prof.oak.pic" -ChiefPic:: -ScientistPic:: INCBIN "pic/trainer/scientist.pic" -GiovanniPic:: INCBIN "pic/trainer/giovanni.pic" -RocketPic:: INCBIN "pic/trainer/rocket.pic" -CooltrainerMPic:: INCBIN "pic/trainer/cooltrainerm.pic" -CooltrainerFPic:: INCBIN "pic/trainer/cooltrainerf.pic" -BrunoPic:: INCBIN "pic/trainer/bruno.pic" -BrockPic:: INCBIN "pic/trainer/brock.pic" -MistyPic:: INCBIN "pic/trainer/misty.pic" -LtSurgePic:: INCBIN "pic/trainer/lt.surge.pic" -ErikaPic:: INCBIN "pic/trainer/erika.pic" -KogaPic:: INCBIN "pic/trainer/koga.pic" -BlainePic:: INCBIN "pic/trainer/blaine.pic" -SabrinaPic:: INCBIN "pic/trainer/sabrina.pic" -GentlemanPic:: INCBIN "pic/trainer/gentleman.pic" -Rival2Pic:: INCBIN "pic/trainer/rival2.pic" -Rival3Pic:: INCBIN "pic/trainer/rival3.pic" -LoreleiPic:: INCBIN "pic/trainer/lorelei.pic" -ChannelerPic:: INCBIN "pic/trainer/channeler.pic" -AgathaPic:: INCBIN "pic/trainer/agatha.pic" -LancePic:: INCBIN "pic/trainer/lance.pic" - -INCLUDE "data/mapHeaders/battlecenterm.asm" -INCLUDE "scripts/battlecenterm.asm" -INCLUDE "data/mapObjects/battlecenterm.asm" -BattleCenterMBlocks: INCBIN "maps/battlecenterm.blk" - -INCLUDE "data/mapHeaders/tradecenterm.asm" -INCLUDE "scripts/tradecenterm.asm" -INCLUDE "data/mapObjects/tradecenterm.asm" -TradeCenterMBlocks: INCBIN "maps/tradecenterm.blk" - -INCLUDE "engine/give_pokemon.asm" - -INCLUDE "engine/predefs.asm" - - -SECTION "bank14",ROMX,BANK[$14] - -INCLUDE "data/mapHeaders/route22.asm" -INCLUDE "data/mapObjects/route22.asm" -Route22Blocks: INCBIN "maps/route22.blk" - -INCLUDE "data/mapHeaders/route20.asm" -INCLUDE "data/mapObjects/route20.asm" -Route20Blocks: INCBIN "maps/route20.blk" - -INCLUDE "data/mapHeaders/route23.asm" -INCLUDE "data/mapObjects/route23.asm" -Route23Blocks: INCBIN "maps/route23.blk" - -INCLUDE "data/mapHeaders/route24.asm" -INCLUDE "data/mapObjects/route24.asm" -Route24Blocks: INCBIN "maps/route24.blk" - -INCLUDE "data/mapHeaders/route25.asm" -INCLUDE "data/mapObjects/route25.asm" -Route25Blocks: INCBIN "maps/route25.blk" - -INCLUDE "data/mapHeaders/indigoplateau.asm" -INCLUDE "scripts/indigoplateau.asm" -INCLUDE "data/mapObjects/indigoplateau.asm" -IndigoPlateauBlocks: INCBIN "maps/indigoplateau.blk" - -INCLUDE "data/mapHeaders/saffroncity.asm" -INCLUDE "data/mapObjects/saffroncity.asm" -SaffronCityBlocks: INCBIN "maps/saffroncity.blk" -INCLUDE "scripts/saffroncity.asm" - -INCLUDE "scripts/route20.asm" -INCLUDE "scripts/route22.asm" -INCLUDE "scripts/route23.asm" -INCLUDE "scripts/route24.asm" -INCLUDE "scripts/route25.asm" - -INCLUDE "data/mapHeaders/victoryroad2.asm" -INCLUDE "scripts/victoryroad2.asm" -INCLUDE "data/mapObjects/victoryroad2.asm" -VictoryRoad2Blocks: INCBIN "maps/victoryroad2.blk" - -INCLUDE "data/mapHeaders/mtmoon2.asm" -INCLUDE "scripts/mtmoon2.asm" -INCLUDE "data/mapObjects/mtmoon2.asm" -MtMoon2Blocks: INCBIN "maps/mtmoon2.blk" - -INCLUDE "data/mapHeaders/silphco7.asm" -INCLUDE "scripts/silphco7.asm" -INCLUDE "data/mapObjects/silphco7.asm" -SilphCo7Blocks: INCBIN "maps/silphco7.blk" - -INCLUDE "data/mapHeaders/mansion2.asm" -INCLUDE "scripts/mansion2.asm" -INCLUDE "data/mapObjects/mansion2.asm" -Mansion2Blocks: INCBIN "maps/mansion2.blk" - -INCLUDE "data/mapHeaders/mansion3.asm" -INCLUDE "scripts/mansion3.asm" -INCLUDE "data/mapObjects/mansion3.asm" -Mansion3Blocks: INCBIN "maps/mansion3.blk" - -INCLUDE "data/mapHeaders/mansion4.asm" -INCLUDE "scripts/mansion4.asm" -INCLUDE "data/mapObjects/mansion4.asm" -Mansion4Blocks: INCBIN "maps/mansion4.blk" - -INCLUDE "engine/battle/init_battle_variables.asm" -INCLUDE "engine/battle/moveEffects/paralyze_effect.asm" - -INCLUDE "engine/overworld/card_key.asm" - -INCLUDE "engine/menu/prize_menu.asm" - -INCLUDE "engine/hidden_object_functions14.asm" - - -SECTION "bank15",ROMX,BANK[$15] - -INCLUDE "data/mapHeaders/route2.asm" -INCLUDE "data/mapObjects/route2.asm" -Route2Blocks: INCBIN "maps/route2.blk" - -INCLUDE "data/mapHeaders/route3.asm" -INCLUDE "data/mapObjects/route3.asm" -Route3Blocks: INCBIN "maps/route3.blk" - -INCLUDE "data/mapHeaders/route4.asm" -INCLUDE "data/mapObjects/route4.asm" -Route4Blocks: INCBIN "maps/route4.blk" - -INCLUDE "data/mapHeaders/route5.asm" -INCLUDE "data/mapObjects/route5.asm" -Route5Blocks: INCBIN "maps/route5.blk" - -INCLUDE "data/mapHeaders/route9.asm" -INCLUDE "data/mapObjects/route9.asm" -Route9Blocks: INCBIN "maps/route9.blk" - -INCLUDE "data/mapHeaders/route13.asm" -INCLUDE "data/mapObjects/route13.asm" -Route13Blocks: INCBIN "maps/route13.blk" - -INCLUDE "data/mapHeaders/route14.asm" -INCLUDE "data/mapObjects/route14.asm" -Route14Blocks: INCBIN "maps/route14.blk" - -INCLUDE "data/mapHeaders/route17.asm" -INCLUDE "data/mapObjects/route17.asm" -Route17Blocks: INCBIN "maps/route17.blk" - -INCLUDE "data/mapHeaders/route19.asm" -INCLUDE "data/mapObjects/route19.asm" -IF DEF(_OPTION_BEACH_HOUSE) -Route19Blocks: INCBIN "maps/route19-yellow.blk" -ELSE -Route19Blocks: INCBIN "maps/route19.blk" -ENDC - -INCLUDE "data/mapHeaders/route21.asm" -INCLUDE "data/mapObjects/route21.asm" -Route21Blocks: INCBIN "maps/route21.blk" - -VermilionHouse2Blocks: -Route12HouseBlocks: -DayCareMBlocks: INCBIN "maps/daycarem.blk" - -FuchsiaHouse3Blocks: INCBIN "maps/fuchsiahouse3.blk" - -INCLUDE "engine/battle/experience.asm" - -INCLUDE "scripts/route2.asm" -INCLUDE "scripts/route3.asm" -INCLUDE "scripts/route4.asm" -INCLUDE "scripts/route5.asm" -INCLUDE "scripts/route9.asm" -INCLUDE "scripts/route13.asm" -INCLUDE "scripts/route14.asm" -INCLUDE "scripts/route17.asm" -INCLUDE "scripts/route19.asm" -INCLUDE "scripts/route21.asm" - -INCLUDE "data/mapHeaders/vermilionhouse2.asm" -INCLUDE "scripts/vermilionhouse2.asm" -INCLUDE "data/mapObjects/vermilionhouse2.asm" - -INCLUDE "data/mapHeaders/celadonmart2.asm" -INCLUDE "scripts/celadonmart2.asm" -INCLUDE "data/mapObjects/celadonmart2.asm" -CeladonMart2Blocks: INCBIN "maps/celadonmart2.blk" - -INCLUDE "data/mapHeaders/fuchsiahouse3.asm" -INCLUDE "scripts/fuchsiahouse3.asm" -INCLUDE "data/mapObjects/fuchsiahouse3.asm" - -INCLUDE "data/mapHeaders/daycarem.asm" -INCLUDE "scripts/daycarem.asm" -INCLUDE "data/mapObjects/daycarem.asm" - -INCLUDE "data/mapHeaders/route12house.asm" -INCLUDE "scripts/route12house.asm" -INCLUDE "data/mapObjects/route12house.asm" - -INCLUDE "data/mapHeaders/silphco8.asm" -INCLUDE "scripts/silphco8.asm" -INCLUDE "data/mapObjects/silphco8.asm" -SilphCo8Blocks: INCBIN "maps/silphco8.blk" - -INCLUDE "engine/menu/diploma.asm" - -INCLUDE "engine/overworld/trainers.asm" - - -SECTION "bank16",ROMX,BANK[$16] - -INCLUDE "data/mapHeaders/route6.asm" -INCLUDE "data/mapObjects/route6.asm" -Route6Blocks: INCBIN "maps/route6.blk" - -INCLUDE "data/mapHeaders/route8.asm" -INCLUDE "data/mapObjects/route8.asm" -Route8Blocks: INCBIN "maps/route8.blk" - -INCLUDE "data/mapHeaders/route10.asm" -INCLUDE "data/mapObjects/route10.asm" -Route10Blocks: INCBIN "maps/route10.blk" - -INCLUDE "data/mapHeaders/route11.asm" -INCLUDE "data/mapObjects/route11.asm" -Route11Blocks: INCBIN "maps/route11.blk" - -INCLUDE "data/mapHeaders/route12.asm" -INCLUDE "data/mapObjects/route12.asm" -Route12Blocks: INCBIN "maps/route12.blk" - -INCLUDE "data/mapHeaders/route15.asm" -INCLUDE "data/mapObjects/route15.asm" -Route15Blocks: INCBIN "maps/route15.blk" - -INCLUDE "data/mapHeaders/route16.asm" -INCLUDE "data/mapObjects/route16.asm" -Route16Blocks: INCBIN "maps/route16.blk" - -INCLUDE "data/mapHeaders/route18.asm" -INCLUDE "data/mapObjects/route18.asm" -Route18Blocks: INCBIN "maps/route18.blk" - - INCBIN "maps/unusedblocks58d7d.blk" - -INCLUDE "engine/battle/common_text.asm" - -INCLUDE "engine/experience.asm" - -INCLUDE "engine/overworld/oaks_aide.asm" - -INCLUDE "scripts/route6.asm" -INCLUDE "scripts/route8.asm" -INCLUDE "scripts/route10.asm" -INCLUDE "scripts/route11.asm" -INCLUDE "scripts/route12.asm" -INCLUDE "scripts/route15.asm" -INCLUDE "scripts/route16.asm" -INCLUDE "scripts/route18.asm" - -INCLUDE "data/mapHeaders/fanclub.asm" -INCLUDE "scripts/fanclub.asm" -INCLUDE "data/mapObjects/fanclub.asm" -FanClubBlocks: - INCBIN "maps/fanclub.blk" - -INCLUDE "data/mapHeaders/silphco2.asm" -INCLUDE "scripts/silphco2.asm" -INCLUDE "data/mapObjects/silphco2.asm" -SilphCo2Blocks: - INCBIN "maps/silphco2.blk" - -INCLUDE "data/mapHeaders/silphco3.asm" -INCLUDE "scripts/silphco3.asm" -INCLUDE "data/mapObjects/silphco3.asm" -SilphCo3Blocks: - INCBIN "maps/silphco3.blk" - -INCLUDE "data/mapHeaders/silphco10.asm" -INCLUDE "scripts/silphco10.asm" -INCLUDE "data/mapObjects/silphco10.asm" -SilphCo10Blocks: - INCBIN "maps/silphco10.blk" - -INCLUDE "data/mapHeaders/lance.asm" -INCLUDE "scripts/lance.asm" -INCLUDE "data/mapObjects/lance.asm" -LanceBlocks: - INCBIN "maps/lance.blk" - -INCLUDE "data/mapHeaders/halloffameroom.asm" -INCLUDE "scripts/halloffameroom.asm" -INCLUDE "data/mapObjects/halloffameroom.asm" -HallofFameRoomBlocks: - INCBIN "maps/halloffameroom.blk" - -INCLUDE "engine/overworld/saffron_guards.asm" - - -SECTION "bank17",ROMX,BANK[$17] - -SaffronMartBlocks: -LavenderMartBlocks: -CeruleanMartBlocks: -VermilionMartBlocks: INCBIN "maps/vermilionmart.blk" - -CopycatsHouse2FBlocks: -RedsHouse2FBlocks: INCBIN "maps/redshouse2f.blk" - -Museum1FBlocks: INCBIN "maps/museum1f.blk" - -Museum2FBlocks: INCBIN "maps/museum2f.blk" - -SaffronPokecenterBlocks: -VermilionPokecenterBlocks: -LavenderPokecenterBlocks: -PewterPokecenterBlocks: INCBIN "maps/pewterpokecenter.blk" - -UndergroundPathEntranceRoute7Blocks: -UndergroundPathEntranceRoute7CopyBlocks: -UndergroundPathEntranceRoute6Blocks: -UndergroundPathEntranceRoute5Blocks: INCBIN "maps/undergroundpathentranceroute5.blk" - -Route2GateBlocks: -ViridianForestEntranceBlocks: -ViridianForestExitBlocks: INCBIN "maps/viridianforestexit.blk" - -INCLUDE "data/mapHeaders/redshouse2f.asm" -INCLUDE "scripts/redshouse2f.asm" -INCLUDE "data/mapObjects/redshouse2f.asm" - -INCLUDE "engine/predefs17.asm" - -INCLUDE "data/mapHeaders/museum1f.asm" -INCLUDE "scripts/museum1f.asm" -INCLUDE "data/mapObjects/museum1f.asm" - -INCLUDE "data/mapHeaders/museum2f.asm" -INCLUDE "scripts/museum2f.asm" -INCLUDE "data/mapObjects/museum2f.asm" - -INCLUDE "data/mapHeaders/pewtergym.asm" -INCLUDE "scripts/pewtergym.asm" -INCLUDE "data/mapObjects/pewtergym.asm" -PewterGymBlocks: INCBIN "maps/pewtergym.blk" - -INCLUDE "data/mapHeaders/pewterpokecenter.asm" -INCLUDE "scripts/pewterpokecenter.asm" -INCLUDE "data/mapObjects/pewterpokecenter.asm" - -INCLUDE "data/mapHeaders/ceruleanpokecenter.asm" -INCLUDE "scripts/ceruleanpokecenter.asm" -INCLUDE "data/mapObjects/ceruleanpokecenter.asm" -CeruleanPokecenterBlocks: INCBIN "maps/ceruleanpokecenter.blk" - -INCLUDE "data/mapHeaders/ceruleangym.asm" -INCLUDE "scripts/ceruleangym.asm" -INCLUDE "data/mapObjects/ceruleangym.asm" -CeruleanGymBlocks: INCBIN "maps/ceruleangym.blk" - -INCLUDE "data/mapHeaders/ceruleanmart.asm" -INCLUDE "scripts/ceruleanmart.asm" -INCLUDE "data/mapObjects/ceruleanmart.asm" - -INCLUDE "data/mapHeaders/lavenderpokecenter.asm" -INCLUDE "scripts/lavenderpokecenter.asm" -INCLUDE "data/mapObjects/lavenderpokecenter.asm" - -INCLUDE "data/mapHeaders/lavendermart.asm" -INCLUDE "scripts/lavendermart.asm" -INCLUDE "data/mapObjects/lavendermart.asm" - -INCLUDE "data/mapHeaders/vermilionpokecenter.asm" -INCLUDE "scripts/vermilionpokecenter.asm" -INCLUDE "data/mapObjects/vermilionpokecenter.asm" - -INCLUDE "data/mapHeaders/vermilionmart.asm" -INCLUDE "scripts/vermilionmart.asm" -INCLUDE "data/mapObjects/vermilionmart.asm" - -INCLUDE "data/mapHeaders/vermiliongym.asm" -INCLUDE "scripts/vermiliongym.asm" -INCLUDE "data/mapObjects/vermiliongym.asm" -VermilionGymBlocks: INCBIN "maps/vermiliongym.blk" - -INCLUDE "data/mapHeaders/copycatshouse2f.asm" -INCLUDE "scripts/copycatshouse2f.asm" -INCLUDE "data/mapObjects/copycatshouse2f.asm" - -INCLUDE "data/mapHeaders/fightingdojo.asm" -INCLUDE "scripts/fightingdojo.asm" -INCLUDE "data/mapObjects/fightingdojo.asm" -FightingDojoBlocks: INCBIN "maps/fightingdojo.blk" - -INCLUDE "data/mapHeaders/saffrongym.asm" -INCLUDE "scripts/saffrongym.asm" -INCLUDE "data/mapObjects/saffrongym.asm" -SaffronGymBlocks: INCBIN "maps/saffrongym.blk" - -INCLUDE "data/mapHeaders/saffronmart.asm" -INCLUDE "scripts/saffronmart.asm" -INCLUDE "data/mapObjects/saffronmart.asm" - -INCLUDE "data/mapHeaders/silphco1.asm" -INCLUDE "scripts/silphco1.asm" -INCLUDE "data/mapObjects/silphco1.asm" -SilphCo1Blocks: INCBIN "maps/silphco1.blk" - -INCLUDE "data/mapHeaders/saffronpokecenter.asm" -INCLUDE "scripts/saffronpokecenter.asm" -INCLUDE "data/mapObjects/saffronpokecenter.asm" - -INCLUDE "data/mapHeaders/viridianforestexit.asm" -INCLUDE "scripts/viridianforestexit.asm" -INCLUDE "data/mapObjects/viridianforestexit.asm" - -INCLUDE "data/mapHeaders/route2gate.asm" -INCLUDE "scripts/route2gate.asm" -INCLUDE "data/mapObjects/route2gate.asm" - -INCLUDE "data/mapHeaders/viridianforestentrance.asm" -INCLUDE "scripts/viridianforestentrance.asm" -INCLUDE "data/mapObjects/viridianforestentrance.asm" - -INCLUDE "data/mapHeaders/undergroundpathentranceroute5.asm" -INCLUDE "scripts/undergroundpathentranceroute5.asm" -INCLUDE "data/mapObjects/undergroundpathentranceroute5.asm" - -INCLUDE "data/mapHeaders/undergroundpathentranceroute6.asm" -INCLUDE "scripts/undergroundpathentranceroute6.asm" -INCLUDE "data/mapObjects/undergroundpathentranceroute6.asm" - -INCLUDE "data/mapHeaders/undergroundpathentranceroute7.asm" -INCLUDE "scripts/undergroundpathentranceroute7.asm" -INCLUDE "data/mapObjects/undergroundpathentranceroute7.asm" - -INCLUDE "data/mapHeaders/undergroundpathentranceroute7copy.asm" -INCLUDE "scripts/undergroundpathentranceroute7copy.asm" -INCLUDE "data/mapObjects/undergroundpathentranceroute7copy.asm" - -INCLUDE "data/mapHeaders/silphco9.asm" -INCLUDE "scripts/silphco9.asm" -INCLUDE "data/mapObjects/silphco9.asm" -SilphCo9Blocks: INCBIN "maps/silphco9.blk" - -INCLUDE "data/mapHeaders/victoryroad1.asm" -INCLUDE "scripts/victoryroad1.asm" -INCLUDE "data/mapObjects/victoryroad1.asm" -VictoryRoad1Blocks: INCBIN "maps/victoryroad1.blk" - -INCLUDE "engine/predefs17_2.asm" - -INCLUDE "engine/hidden_object_functions17.asm" - - -SECTION "bank18",ROMX,BANK[$18] - -ViridianForestBlocks: INCBIN "maps/viridianforest.blk" -UndergroundPathNSBlocks: INCBIN "maps/undergroundpathns.blk" -UndergroundPathWEBlocks: INCBIN "maps/undergroundpathwe.blk" - - INCBIN "maps/unusedblocks60258.blk" - -SSAnne10Blocks: -SSAnne9Blocks: INCBIN "maps/ssanne9.blk" - -INCLUDE "data/mapHeaders/pokemontower1.asm" -INCLUDE "scripts/pokemontower1.asm" -INCLUDE "data/mapObjects/pokemontower1.asm" -PokemonTower1Blocks: INCBIN "maps/pokemontower1.blk" - -INCLUDE "data/mapHeaders/pokemontower2.asm" -INCLUDE "scripts/pokemontower2.asm" -INCLUDE "data/mapObjects/pokemontower2.asm" -PokemonTower2Blocks: INCBIN "maps/pokemontower2.blk" - -INCLUDE "data/mapHeaders/pokemontower3.asm" -INCLUDE "scripts/pokemontower3.asm" -INCLUDE "data/mapObjects/pokemontower3.asm" -PokemonTower3Blocks: INCBIN "maps/pokemontower3.blk" - -INCLUDE "data/mapHeaders/pokemontower4.asm" -INCLUDE "scripts/pokemontower4.asm" -INCLUDE "data/mapObjects/pokemontower4.asm" -PokemonTower4Blocks: INCBIN "maps/pokemontower4.blk" - -INCLUDE "data/mapHeaders/pokemontower5.asm" -INCLUDE "scripts/pokemontower5.asm" -INCLUDE "data/mapObjects/pokemontower5.asm" -PokemonTower5Blocks: INCBIN "maps/pokemontower5.blk" - -INCLUDE "data/mapHeaders/pokemontower6.asm" -INCLUDE "scripts/pokemontower6.asm" -INCLUDE "data/mapObjects/pokemontower6.asm" -PokemonTower6Blocks: INCBIN "maps/pokemontower6.blk" - - INCBIN "maps/unusedblocks60cef.blk" - -INCLUDE "data/mapHeaders/pokemontower7.asm" -INCLUDE "scripts/pokemontower7.asm" -INCLUDE "data/mapObjects/pokemontower7.asm" -PokemonTower7Blocks: INCBIN "maps/pokemontower7.blk" - -INCLUDE "data/mapHeaders/celadonmart1.asm" -INCLUDE "scripts/celadonmart1.asm" -INCLUDE "data/mapObjects/celadonmart1.asm" -CeladonMart1Blocks: INCBIN "maps/celadonmart1.blk" - -INCLUDE "engine/overworld/cinnabar_lab.asm" - -INCLUDE "data/mapHeaders/viridianforest.asm" -INCLUDE "scripts/viridianforest.asm" -INCLUDE "data/mapObjects/viridianforest.asm" - -INCLUDE "data/mapHeaders/ssanne1.asm" -INCLUDE "scripts/ssanne1.asm" -INCLUDE "data/mapObjects/ssanne1.asm" -SSAnne1Blocks: INCBIN "maps/ssanne1.blk" - -INCLUDE "data/mapHeaders/ssanne2.asm" -INCLUDE "scripts/ssanne2.asm" -INCLUDE "data/mapObjects/ssanne2.asm" -SSAnne2Blocks: INCBIN "maps/ssanne2.blk" - -INCLUDE "data/mapHeaders/ssanne4.asm" -INCLUDE "scripts/ssanne4.asm" -INCLUDE "data/mapObjects/ssanne4.asm" -SSAnne4Blocks: INCBIN "maps/ssanne4.blk" - -INCLUDE "data/mapHeaders/ssanne5.asm" -INCLUDE "scripts/ssanne5.asm" -INCLUDE "data/mapObjects/ssanne5.asm" -SSAnne5Blocks: INCBIN "maps/ssanne5.blk" - -INCLUDE "data/mapHeaders/ssanne6.asm" -INCLUDE "scripts/ssanne6.asm" -INCLUDE "data/mapObjects/ssanne6.asm" -SSAnne6Blocks: INCBIN "maps/ssanne6.blk" - -INCLUDE "data/mapHeaders/ssanne7.asm" -INCLUDE "scripts/ssanne7.asm" -INCLUDE "data/mapObjects/ssanne7.asm" -SSAnne7Blocks: INCBIN "maps/ssanne7.blk" - -INCLUDE "data/mapHeaders/ssanne8.asm" -INCLUDE "scripts/ssanne8.asm" -INCLUDE "data/mapObjects/ssanne8.asm" -SSAnne8Blocks: INCBIN "maps/ssanne8.blk" - -INCLUDE "data/mapHeaders/ssanne9.asm" -INCLUDE "scripts/ssanne9.asm" -INCLUDE "data/mapObjects/ssanne9.asm" - -INCLUDE "data/mapHeaders/ssanne10.asm" -INCLUDE "scripts/ssanne10.asm" -INCLUDE "data/mapObjects/ssanne10.asm" - -INCLUDE "data/mapHeaders/undergroundpathns.asm" -INCLUDE "scripts/undergroundpathns.asm" -INCLUDE "data/mapObjects/undergroundpathns.asm" - -INCLUDE "data/mapHeaders/undergroundpathwe.asm" -INCLUDE "scripts/undergroundpathwe.asm" -INCLUDE "data/mapObjects/undergroundpathwe.asm" - -INCLUDE "data/mapHeaders/diglettscave.asm" -INCLUDE "scripts/diglettscave.asm" -INCLUDE "data/mapObjects/diglettscave.asm" -DiglettsCaveBlocks: INCBIN "maps/diglettscave.blk" - -INCLUDE "data/mapHeaders/silphco11.asm" -INCLUDE "scripts/silphco11.asm" -INCLUDE "data/mapObjects/silphco11.asm" -SilphCo11Blocks: INCBIN "maps/silphco11.blk" - -INCLUDE "engine/hidden_object_functions18.asm" - - -SECTION "bank19",ROMX,BANK[$19] - -Overworld_GFX: INCBIN "gfx/tilesets/overworld.t2.2bpp" -Overworld_Block: INCBIN "gfx/blocksets/overworld.bst" - -RedsHouse1_GFX: -RedsHouse2_GFX: INCBIN "gfx/tilesets/reds_house.t7.2bpp" -RedsHouse1_Block: -RedsHouse2_Block: INCBIN "gfx/blocksets/reds_house.bst" - -House_GFX: INCBIN "gfx/tilesets/house.t2.2bpp" -House_Block: INCBIN "gfx/blocksets/house.bst" -Mansion_GFX: INCBIN "gfx/tilesets/mansion.t2.2bpp" -Mansion_Block: INCBIN "gfx/blocksets/mansion.bst" -ShipPort_GFX: INCBIN "gfx/tilesets/ship_port.t2.2bpp" -ShipPort_Block: INCBIN "gfx/blocksets/ship_port.bst" -Interior_GFX: INCBIN "gfx/tilesets/interior.t1.2bpp" -Interior_Block: INCBIN "gfx/blocksets/interior.bst" -Plateau_GFX: INCBIN "gfx/tilesets/plateau.t10.2bpp" -Plateau_Block: INCBIN "gfx/blocksets/plateau.bst" - - -SECTION "bank1A",ROMX,BANK[$1A] - -INCLUDE "engine/battle/decrement_pp.asm" - -Version_GFX: -IF DEF(_RED) - INCBIN "gfx/red/redgreenversion.1bpp" ; 10 tiles -ENDC -IF DEF(_BLUE) - INCBIN "gfx/blue/blueversion.1bpp" ; 8 tiles -ENDC - -Dojo_GFX: -Gym_GFX: INCBIN "gfx/tilesets/gym.2bpp" -Dojo_Block: -Gym_Block: INCBIN "gfx/blocksets/gym.bst" - -Mart_GFX: -Pokecenter_GFX: INCBIN "gfx/tilesets/pokecenter.2bpp" -Mart_Block: -Pokecenter_Block: INCBIN "gfx/blocksets/pokecenter.bst" - -ForestGate_GFX: -Museum_GFX: -Gate_GFX: INCBIN "gfx/tilesets/gate.t1.2bpp" -ForestGate_Block: -Museum_Block: -Gate_Block: INCBIN "gfx/blocksets/gate.bst" - -Forest_GFX: INCBIN "gfx/tilesets/forest.2bpp" -Forest_Block: INCBIN "gfx/blocksets/forest.bst" -Facility_GFX: INCBIN "gfx/tilesets/facility.2bpp" -Facility_Block: INCBIN "gfx/blocksets/facility.bst" - - -SECTION "bank1B",ROMX,BANK[$1B] - -Cemetery_GFX: INCBIN "gfx/tilesets/cemetery.t4.2bpp" -Cemetery_Block: INCBIN "gfx/blocksets/cemetery.bst" -Cavern_GFX: INCBIN "gfx/tilesets/cavern.t14.2bpp" -Cavern_Block: INCBIN "gfx/blocksets/cavern.bst" -Lobby_GFX: INCBIN "gfx/tilesets/lobby.t2.2bpp" -Lobby_Block: INCBIN "gfx/blocksets/lobby.bst" -Ship_GFX: INCBIN "gfx/tilesets/ship.t6.2bpp" -Ship_Block: INCBIN "gfx/blocksets/ship.bst" -Lab_GFX: INCBIN "gfx/tilesets/lab.t4.2bpp" -Lab_Block: INCBIN "gfx/blocksets/lab.bst" -Club_GFX: INCBIN "gfx/tilesets/club.t5.2bpp" -Club_Block: INCBIN "gfx/blocksets/club.bst" -Underground_GFX: INCBIN "gfx/tilesets/underground.t7.2bpp" -Underground_Block: INCBIN "gfx/blocksets/underground.bst" - - -SECTION "bank1C",ROMX,BANK[$1C] - -INCLUDE "engine/gamefreak.asm" -INCLUDE "engine/hall_of_fame.asm" -INCLUDE "engine/overworld/healing_machine.asm" -INCLUDE "engine/overworld/player_animations.asm" -INCLUDE "engine/battle/ghost_marowak_anim.asm" -INCLUDE "engine/battle/battle_transitions.asm" -INCLUDE "engine/town_map.asm" -INCLUDE "engine/mon_party_sprites.asm" -INCLUDE "engine/in_game_trades.asm" -INCLUDE "engine/palettes.asm" -INCLUDE "engine/save.asm" - - -SECTION "bank1D",ROMX,BANK[$1D] - -CopycatsHouse1FBlocks: INCBIN "maps/copycatshouse1f.blk" - -CinnabarMartBlocks: -PewterMartBlocks: INCBIN "maps/pewtermart.blk" - -FuchsiaHouse1Blocks: INCBIN "maps/fuchsiahouse1.blk" - -CinnabarPokecenterBlocks: -FuchsiaPokecenterBlocks: INCBIN "maps/fuchsiapokecenter.blk" - -CeruleanHouse2Blocks: INCBIN "maps/ceruleanhouse2.blk" - -INCLUDE "engine/HoF_room_pc.asm" - -INCLUDE "engine/status_ailments.asm" - -INCLUDE "engine/items/itemfinder.asm" - -INCLUDE "scripts/ceruleancity2.asm" - -INCLUDE "data/mapHeaders/viridiangym.asm" -INCLUDE "scripts/viridiangym.asm" -INCLUDE "data/mapObjects/viridiangym.asm" -ViridianGymBlocks: INCBIN "maps/viridiangym.blk" - -INCLUDE "data/mapHeaders/pewtermart.asm" -INCLUDE "scripts/pewtermart.asm" -INCLUDE "data/mapObjects/pewtermart.asm" - -INCLUDE "data/mapHeaders/unknowndungeon1.asm" -INCLUDE "scripts/unknowndungeon1.asm" -INCLUDE "data/mapObjects/unknowndungeon1.asm" -UnknownDungeon1Blocks: INCBIN "maps/unknowndungeon1.blk" - -INCLUDE "data/mapHeaders/ceruleanhouse2.asm" -INCLUDE "scripts/ceruleanhouse2.asm" -INCLUDE "data/mapObjects/ceruleanhouse2.asm" - -INCLUDE "engine/menu/vending_machine.asm" - -INCLUDE "data/mapHeaders/fuchsiahouse1.asm" -INCLUDE "scripts/fuchsiahouse1.asm" -INCLUDE "data/mapObjects/fuchsiahouse1.asm" - -INCLUDE "data/mapHeaders/fuchsiapokecenter.asm" -INCLUDE "scripts/fuchsiapokecenter.asm" -INCLUDE "data/mapObjects/fuchsiapokecenter.asm" - -INCLUDE "data/mapHeaders/fuchsiahouse2.asm" -INCLUDE "scripts/fuchsiahouse2.asm" -INCLUDE "data/mapObjects/fuchsiahouse2.asm" -FuchsiaHouse2Blocks: INCBIN "maps/fuchsiahouse2.blk" - -INCLUDE "data/mapHeaders/safarizoneentrance.asm" -INCLUDE "scripts/safarizoneentrance.asm" -INCLUDE "data/mapObjects/safarizoneentrance.asm" -SafariZoneEntranceBlocks: INCBIN "maps/safarizoneentrance.blk" - -INCLUDE "data/mapHeaders/fuchsiagym.asm" -INCLUDE "scripts/fuchsiagym.asm" -INCLUDE "data/mapObjects/fuchsiagym.asm" -FuchsiaGymBlocks: INCBIN "maps/fuchsiagym.blk" - -INCLUDE "data/mapHeaders/fuchsiameetingroom.asm" -INCLUDE "scripts/fuchsiameetingroom.asm" -INCLUDE "data/mapObjects/fuchsiameetingroom.asm" -FuchsiaMeetingRoomBlocks: INCBIN "maps/fuchsiameetingroom.blk" - -INCLUDE "data/mapHeaders/cinnabargym.asm" -INCLUDE "scripts/cinnabargym.asm" -INCLUDE "data/mapObjects/cinnabargym.asm" -CinnabarGymBlocks: INCBIN "maps/cinnabargym.blk" - -INCLUDE "data/mapHeaders/lab1.asm" -INCLUDE "scripts/lab1.asm" -INCLUDE "data/mapObjects/lab1.asm" -Lab1Blocks: INCBIN "maps/lab1.blk" - -INCLUDE "data/mapHeaders/lab2.asm" -INCLUDE "scripts/lab2.asm" -INCLUDE "data/mapObjects/lab2.asm" -Lab2Blocks: INCBIN "maps/lab2.blk" - -INCLUDE "data/mapHeaders/lab3.asm" -INCLUDE "scripts/lab3.asm" -INCLUDE "data/mapObjects/lab3.asm" -Lab3Blocks: INCBIN "maps/lab3.blk" - -INCLUDE "data/mapHeaders/lab4.asm" -INCLUDE "scripts/lab4.asm" -INCLUDE "data/mapObjects/lab4.asm" -Lab4Blocks: INCBIN "maps/lab4.blk" - -INCLUDE "data/mapHeaders/cinnabarpokecenter.asm" -INCLUDE "scripts/cinnabarpokecenter.asm" -INCLUDE "data/mapObjects/cinnabarpokecenter.asm" - -INCLUDE "data/mapHeaders/cinnabarmart.asm" -INCLUDE "scripts/cinnabarmart.asm" -INCLUDE "data/mapObjects/cinnabarmart.asm" - -INCLUDE "data/mapHeaders/copycatshouse1f.asm" -INCLUDE "scripts/copycatshouse1f.asm" -INCLUDE "data/mapObjects/copycatshouse1f.asm" - -INCLUDE "data/mapHeaders/gary.asm" -INCLUDE "scripts/gary.asm" -INCLUDE "data/mapObjects/gary.asm" -GaryBlocks: INCBIN "maps/gary.blk" - -INCLUDE "data/mapHeaders/lorelei.asm" -INCLUDE "scripts/lorelei.asm" -INCLUDE "data/mapObjects/lorelei.asm" -LoreleiBlocks: INCBIN "maps/lorelei.blk" - -INCLUDE "data/mapHeaders/bruno.asm" -INCLUDE "scripts/bruno.asm" -INCLUDE "data/mapObjects/bruno.asm" -BrunoBlocks: INCBIN "maps/bruno.blk" - -INCLUDE "data/mapHeaders/agatha.asm" -INCLUDE "scripts/agatha.asm" -INCLUDE "data/mapObjects/agatha.asm" -AgathaBlocks: INCBIN "maps/agatha.blk" - -INCLUDE "engine/menu/league_pc.asm" - -INCLUDE "engine/overworld/hidden_items.asm" - - -SECTION "bank1E",ROMX,BANK[$1E] - -INCLUDE "engine/battle/animations.asm" - -INCLUDE "engine/overworld/cut2.asm" - -INCLUDE "engine/overworld/ssanne.asm" - -RedFishingTilesFront: INCBIN "gfx/red_fishing_tile_front.2bpp" -RedFishingTilesBack: INCBIN "gfx/red_fishing_tile_back.2bpp" -RedFishingTilesSide: INCBIN "gfx/red_fishing_tile_side.2bpp" -RedFishingRodTiles: INCBIN "gfx/red_fishingrod_tiles.2bpp" - -INCLUDE "data/animations.asm" - -INCLUDE "engine/evolution.asm" - -INCLUDE "engine/overworld/elevator.asm" - -INCLUDE "engine/items/tm_prices.asm" - -IF DEF(_OPTION_BEACH_HOUSE) -SECTION "bank3C",ROMX[$4314],BANK[$3C] - -BeachHouse_GFX: - INCBIN "gfx/tilesets/beachhouse.2bpp" - -BeachHouse_Block: - INCBIN "gfx/blocksets/beachhouse.bst" -ENDC - -SECTION "bank3d",ROMX,BANK[$3D] - -INCLUDE "engine/random.asm" +INCLUDE "constants.asm"
+
+NPC_SPRITES_1 EQU $4
+NPC_SPRITES_2 EQU $5
+
+GFX EQU $4
+
+PICS_1 EQU $9
+PICS_2 EQU $A
+PICS_3 EQU $B
+PICS_4 EQU $C
+PICS_5 EQU $D
+
+
+INCLUDE "home.asm"
+
+
+SECTION "bank1",ROMX,BANK[$1]
+
+INCLUDE "data/facing.asm"
+
+ResetStatusAndHalveMoneyOnBlackout::
+; Reset player status on blackout.
+ xor a
+ ld [wBattleResult], a
+ ld [wWalkBikeSurfState], a
+ ld [W_ISINBATTLE], a
+ ld [wMapPalOffset], a
+ ld [wNPCMovementScriptFunctionNum], a
+ ld [hJoyHeld], a
+ ld [wNPCMovementScriptPointerTableNum], a
+ ld [wFlags_0xcd60], a
+
+ ld [$ff9f], a
+ ld [$ff9f + 1], a
+ ld [$ff9f + 2], a
+ call HasEnoughMoney
+ jr c, .lostmoney ; never happens
+
+ ; Halve the player's money.
+ ld a, [wPlayerMoney]
+ ld [$ff9f], a
+ ld a, [wPlayerMoney + 1]
+ ld [$ff9f + 1], a
+ ld a, [wPlayerMoney + 2]
+ ld [$ff9f + 2], a
+ xor a
+ ld [$ffa2], a
+ ld [$ffa3], a
+ ld a, 2
+ ld [$ffa4], a
+ predef DivideBCDPredef3
+ ld a, [$ffa2]
+ ld [wPlayerMoney], a
+ ld a, [$ffa2 + 1]
+ ld [wPlayerMoney + 1], a
+ ld a, [$ffa2 + 2]
+ ld [wPlayerMoney + 2], a
+
+.lostmoney
+ ld hl, wd732
+ set 2, [hl]
+ res 3, [hl]
+ set 6, [hl]
+ ld a, %11111111
+ ld [wJoyIgnore], a
+ predef_jump HealParty
+
+
+MewPicFront:: INCBIN "pic/bmon/mew.pic"
+MewPicBack:: INCBIN "pic/monback/mewb.pic"
+INCLUDE "data/baseStats/mew.asm"
+
+INCLUDE "engine/battle/safari_zone.asm"
+
+INCLUDE "engine/titlescreen.asm"
+
+NintenText: db "NINTEN@"
+SonyText: db "SONY@"
+
+
+LoadMonData_:
+; Load monster [wWhichPokemon] from list [wcc49]:
+; 0: partymon
+; 1: enemymon
+; 2: boxmon
+; 3: daycaremon
+; Return monster id at wcf91 and its data at wLoadedMon.
+; Also load base stats at W_MONHDEXNUM for convenience.
+
+ ld a, [wDayCareMonSpecies]
+ ld [wcf91], a
+ ld a, [wcc49]
+ cp 3
+ jr z, .GetMonHeader
+
+ ld a, [wWhichPokemon]
+ ld e, a
+ callab GetMonSpecies
+
+.GetMonHeader
+ ld a, [wcf91]
+ ld [wd0b5], a ; input for GetMonHeader
+ call GetMonHeader
+
+ ld hl, wPartyMons
+ ld bc, wPartyMon2 - wPartyMon1
+ ld a, [wcc49]
+ cp 1
+ jr c, .getMonEntry
+
+ ld hl, wEnemyMons
+ jr z, .getMonEntry
+
+ cp 2
+ ld hl, wBoxMons
+ ld bc, wBoxMon2 - wBoxMon1
+ jr z, .getMonEntry
+
+ ld hl, wDayCareMon
+ jr .copyMonData
+
+.getMonEntry
+ ld a, [wWhichPokemon]
+ call AddNTimes
+
+.copyMonData
+ ld de, wLoadedMon
+ ld bc, wPartyMon2 - wPartyMon1
+ jp CopyData
+
+
+INCLUDE "data/item_prices.asm"
+INCLUDE "text/item_names.asm"
+
+UnusedNames:
+ db "かみなりバッヂ@"
+ db "かいがらバッヂ@"
+ db "おじぞうバッヂ@"
+ db "はやぶさバッヂ@"
+ db "ひんやりバッヂ@"
+ db "なかよしバッヂ@"
+ db "バラバッヂ@"
+ db "ひのたまバッヂ@"
+ db "ゴールドバッヂ@"
+ db "たまご@"
+ db "ひよこ@"
+ db "ブロンズ@"
+ db "シルバー@"
+ db "ゴールド@"
+ db "プチキャプテン@"
+ db "キャプテン@"
+ db "プチマスター@"
+ db "マスター@"
+ db "エクセレント"
+
+INCLUDE "engine/overworld/oam.asm"
+INCLUDE "engine/oam_dma.asm"
+
+PrintWaitingText:
+ hlCoord 3, 10
+ ld b, $1
+ ld c, $b
+ ld a, [W_ISINBATTLE]
+ and a
+ jr z, .asm_4c17
+ call TextBoxBorder
+ jr .asm_4c1a
+.asm_4c17
+ call CableClub_TextBoxBorder
+.asm_4c1a
+ hlCoord 4, 11
+ ld de, WaitingText
+ call PlaceString
+ ld c, 50
+ jp DelayFrames
+
+WaitingText:
+ db "Waiting...!@"
+
+
+_UpdateSprites: ; 4c34 (1:4c34)
+ ld h, $c1
+ inc h
+ ld a, $e ; wSpriteStateData2 + $0e
+.spriteLoop
+ ld l, a
+ sub $e
+ ld c, a
+ ld [H_CURRENTSPRITEOFFSET], a
+ ld a, [hl]
+ and a
+ jr z, .skipSprite ; tests $c2Xe
+ push hl
+ push de
+ push bc
+ call .updateCurrentSprite
+ pop bc
+ pop de
+ pop hl
+.skipSprite
+ ld a, l
+ add $10 ; move to next sprite
+ cp $e ; test for overflow (back at $0e)
+ jr nz, .spriteLoop
+ ret
+.updateCurrentSprite ; 4c54 (1:4c54)
+ cp $1
+ jp nz, UpdateNonPlayerSprite
+ jp UpdatePlayerSprite
+
+UpdateNonPlayerSprite:
+ dec a
+ swap a
+ ld [$ff93], a ; $10 * sprite#
+ ld a, [wNPCMovementScriptSpriteOffset] ; some sprite offset?
+ ld b, a
+ ld a, [H_CURRENTSPRITEOFFSET]
+ cp b
+ jr nz, .unequal
+ jp Func_5236
+.unequal
+ jp Func_4ed1
+
+; This detects if the current sprite (whose offset is at H_CURRENTSPRITEOFFSET)
+; is going to collide with another sprite by looping over the other sprites.
+; The current sprite's offset will be labelled with i (e.g. $c1i0).
+; The loop sprite's offset will labelled with j (e.g. $c1j0).
+;
+; Note that the Y coordinate of the sprite (in [$c1k4]) is one of the following
+; 9 values when the sprite is aligned with the grid: $fc, $0c, $1c, $2c, ..., $7c.
+; The reason that 4 is added below to the coordinate is to make it align with a
+; multiple of $10 to make comparisons easier.
+DetectCollisionBetweenSprites:
+ nop
+
+ ld h, wSpriteStateData1 / $100
+ ld a, [H_CURRENTSPRITEOFFSET]
+ add wSpriteStateData1 % $100
+ ld l, a
+
+ ld a, [hl] ; a = [$c1i0] (picture) (0 if slot is unused)
+ and a ; is this sprite slot slot used?
+ ret z ; return if not used
+
+ ld a, l
+ add 3
+ ld l, a
+
+ ld a, [hli] ; a = [$c1i3] (delta Y) (-1, 0, or 1)
+ call SetSpriteCollisionValues
+
+ ld a, [hli] ; a = [$C1i4] (Y screen coordinate)
+ add 4 ; align with multiple of $10
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving south or
+; subtract 7 from a if moving north.
+ add b
+ and $f0
+ or c
+
+ ld [$ff90], a ; store Y coordinate adjusted for direction of movement
+
+ ld a, [hli] ; a = [$c1i5] (delta X) (-1, 0, or 1)
+ call SetSpriteCollisionValues
+ ld a, [hl] ; a = [$C1i6] (X screen coordinate)
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving east or
+; subtract 7 from a if moving west.
+ add b
+ and $f0
+ or c
+
+ ld [$ff91], a ; store X coordinate adjusted for direction of movement
+
+ ld a, l
+ add 7
+ ld l, a
+
+ xor a
+ ld [hld], a ; zero [$c1id] XXX what's [$c1id] for?
+ ld [hld], a ; zero [$c1ic] (directions in which collisions occurred)
+
+ ld a, [$ff91]
+ ld [hld], a ; [$c1ib] = adjusted X coordiate
+ ld a, [$ff90]
+ ld [hl], a ; [$c1ia] = adjusted Y coordinate
+
+ xor a ; zero the loop counter
+
+.loop
+ ld [$ff8f], a ; store loop counter
+ swap a
+ ld e, a
+ ld a, [H_CURRENTSPRITEOFFSET]
+ cp e ; does the loop sprite match the current sprite?
+ jp z, .next ; go to the next sprite if they match
+
+ ld d, h
+ ld a, [de] ; a = [$c1j0] (picture) (0 if slot is unused)
+ and a ; is this sprite slot slot used?
+ jp z, .next ; go the next sprite if not used
+
+ inc e
+ inc e
+ ld a, [de] ; a = [$c1j2] ($ff means the sprite is offscreen)
+ inc a
+ jp z, .next ; go the next sprite if offscreen
+
+ ld a, [H_CURRENTSPRITEOFFSET]
+ add 10
+ ld l, a
+
+ inc e
+ ld a, [de] ; a = [$c1j3] (delta Y)
+ call SetSpriteCollisionValues
+
+ inc e
+ ld a, [de] ; a = [$C1j4] (Y screen coordinate)
+ add 4 ; align with multiple of $10
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving south or
+; subtract 7 from a if moving north.
+ add b
+ and $f0
+ or c
+
+ sub [hl] ; subtract the adjusted Y coordinate of sprite i ([$c1ia]) from that of sprite j
+
+; calculate the absolute value of the difference to get the distance
+ jr nc, .noCarry1
+ cpl
+ inc a
+.noCarry1
+ ld [$ff90], a ; store the distance between the two sprites' adjusted Y values
+
+; Use the carry flag set by the above subtraction to determine which sprite's
+; Y coordinate is larger. This information is used later to set [$c1ic],
+; which stores which direction the collision occurred in.
+; The following 5 lines set the lowest 2 bits of c, which are later shifted left by 2.
+; If sprite i's Y is larger, set lowest 2 bits of c to 10.
+; If sprite j's Y is larger or both are equal, set lowest 2 bits of c to 01.
+ push af
+ rl c
+ pop af
+ ccf
+ rl c
+
+; If sprite i's delta Y is 0, then b = 7, else b = 9.
+ ld b, 7
+ ld a, [hl] ; a = [$c1ia] (adjusted Y coordinate)
+ and $f
+ jr z, .next1
+ ld b, 9
+
+.next1
+ ld a, [$ff90] ; a = distance between adjusted Y coordinates
+ sub b
+ ld [$ff92], a ; store distance adjusted using sprite i's direction
+ ld a, b
+ ld [$ff90], a ; store 7 or 9 depending on sprite i's delta Y
+ jr c, .checkXDistance
+
+; If sprite j's delta Y is 0, then b = 7, else b = 9.
+ ld b, 7
+ dec e
+ ld a, [de] ; a = [$c1j3] (delta Y)
+ inc e
+ and a
+ jr z, .next2
+ ld b, 9
+
+.next2
+ ld a, [$ff92] ; a = distance adjusted using sprite i's direction
+ sub b ; adjust distance using sprite j's direction
+ jr z, .checkXDistance
+ jr nc, .next ; go to next sprite if distance is still positive after both adjustments
+
+.checkXDistance
+ inc e
+ inc l
+ ld a, [de] ; a = [$c1j5] (delta X)
+
+ push bc
+
+ call SetSpriteCollisionValues
+ inc e
+ ld a, [de] ; a = [$c1j6] (X screen coordinate)
+
+; The effect of the following 3 lines is to
+; add 7 to a if moving east or
+; subtract 7 from a if moving west.
+ add b
+ and $f0
+ or c
+
+ pop bc
+
+ sub [hl] ; subtract the adjusted X coordinate of sprite i ([$c1ib]) from that of sprite j
+
+; calculate the absolute value of the difference to get the distance
+ jr nc, .noCarry2
+ cpl
+ inc a
+.noCarry2
+ ld [$ff91], a ; store the distance between the two sprites' adjusted X values
+
+; Use the carry flag set by the above subtraction to determine which sprite's
+; X coordinate is larger. This information is used later to set [$c1ic],
+; which stores which direction the collision occurred in.
+; The following 5 lines set the lowest 2 bits of c.
+; If sprite i's X is larger, set lowest 2 bits of c to 10.
+; If sprite j's X is larger or both are equal, set lowest 2 bits of c to 01.
+ push af
+ rl c
+ pop af
+ ccf
+ rl c
+
+; If sprite i's delta X is 0, then b = 7, else b = 9.
+ ld b, 7
+ ld a, [hl] ; a = [$c1ib] (adjusted X coordinate)
+ and $f
+ jr z, .next3
+ ld b, 9
+
+.next3
+ ld a, [$ff91] ; a = distance between adjusted X coordinates
+ sub b
+ ld [$ff92], a ; store distance adjusted using sprite i's direction
+ ld a, b
+ ld [$ff91], a ; store 7 or 9 depending on sprite i's delta X
+ jr c, .collision
+
+; If sprite j's delta X is 0, then b = 7, else b = 9.
+ ld b, 7
+ dec e
+ ld a, [de] ; a = [$c1j5] (delta X)
+ inc e
+ and a
+ jr z, .next4
+ ld b, 9
+
+.next4
+ ld a, [$ff92] ; a = distance adjusted using sprite i's direction
+ sub b ; adjust distance using sprite j's direction
+ jr z, .collision
+ jr nc, .next ; go to next sprite if distance is still positive after both adjustments
+
+.collision
+ ld a, [$ff91] ; a = 7 or 9 depending on sprite i's delta X
+ ld b, a
+ ld a, [$ff90] ; a = 7 or 9 depending on sprite i's delta Y
+ inc l
+
+; If delta X isn't 0 and delta Y is 0, then b = %0011, else b = %1100.
+; (note that normally if delta X isn't 0, then delta Y must be 0 and vice versa)
+ cp b
+ jr c, .next5
+ ld b, %1100
+ jr .next6
+.next5
+ ld b, %0011
+
+.next6
+ ld a, c ; c has 2 bits set (one of bits 0-1 is set for the X axis and one of bits 2-3 for the Y axis)
+ and b ; we select either the bit in bits 0-1 or bits 2-3 based on the calculation immediately above
+ or [hl] ; or with existing collision direction bits in [$c1ic]
+ ld [hl], a ; store new value
+ ld a, c ; useless code because a is overwritten before being used again
+
+; set bit in [$c1ie] or [$c1if] to indicate which sprite the collision occurred with
+ inc l
+ inc l
+ ld a, [$ff8f] ; a = loop counter
+ ld de, SpriteCollisionBitTable
+ add a
+ add e
+ ld e, a
+ jr nc, .noCarry3
+ inc d
+.noCarry3
+ ld a, [de]
+ or [hl]
+ ld [hli], a
+ inc de
+ ld a, [de]
+ or [hl]
+ ld [hl], a
+
+.next
+ ld a, [$ff8f] ; a = loop counter
+ inc a
+ cp $10
+ jp nz, .loop
+ ret
+
+; takes delta X or delta Y in a
+; b = delta X/Y
+; c = 0 if delta X/Y is 0
+; c = 7 if delta X/Y is 1
+; c = 9 if delta X/Y is -1
+SetSpriteCollisionValues:
+ and a
+ ld b, 0
+ ld c, 0
+ jr z, .done
+ ld c, 9
+ cp -1
+ jr z, .ok
+ ld c, 7
+ ld a, 0
+.ok
+ ld b, a
+.done
+ ret
+
+SpriteCollisionBitTable:
+ db %00000000,%00000001
+ db %00000000,%00000010
+ db %00000000,%00000100
+ db %00000000,%00001000
+ db %00000000,%00010000
+ db %00000000,%00100000
+ db %00000000,%01000000
+ db %00000000,%10000000
+ db %00000001,%00000000
+ db %00000010,%00000000
+ db %00000100,%00000000
+ db %00001000,%00000000
+ db %00010000,%00000000
+ db %00100000,%00000000
+ db %01000000,%00000000
+ db %10000000,%00000000
+
+TestBattle:
+ ret
+
+.loop
+ call GBPalNormal
+
+ ; Don't mess around
+ ; with obedience.
+ ld a, %10000000 ; EARTHBADGE
+ ld [W_OBTAINEDBADGES], a
+
+ ld hl, W_FLAGS_D733
+ set 0, [hl]
+
+ ; Reset the party.
+ ld hl, wPartyCount
+ xor a
+ ld [hli], a
+ dec a
+ ld [hl], a
+
+ ; Give the player a
+ ; level 20 Rhydon.
+ ld a, RHYDON
+ ld [wcf91], a
+ ld a, 20
+ ld [W_CURENEMYLVL], a
+ xor a
+ ld [wcc49], a
+ ld [W_CURMAP], a
+ call AddPartyMon
+
+ ; Fight against a
+ ; level 20 Rhydon.
+ ld a, RHYDON
+ ld [W_CUROPPONENT], a
+
+ predef InitOpponent
+
+ ; When the battle ends,
+ ; do it all again.
+ ld a, 1
+ ld [wUpdateSpritesEnabled], a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ jr .loop
+
+INCLUDE "engine/overworld/item.asm"
+INCLUDE "engine/overworld/movement.asm"
+
+INCLUDE "engine/cable_club.asm"
+
+LoadTrainerInfoTextBoxTiles: ; 5ae6 (1:5ae6)
+ ld de, TrainerInfoTextBoxTileGraphics ; $7b98
+ ld hl, vChars2 + $760
+ ld bc, (BANK(TrainerInfoTextBoxTileGraphics) << 8) +$09
+ jp CopyVideoData
+
+INCLUDE "engine/menu/main_menu.asm"
+
+INCLUDE "engine/oak_speech.asm"
+
+SpecialWarpIn: ; 62ce (1:62ce)
+ call LoadSpecialWarpData
+ predef LoadTilesetHeader
+ ld hl,wd732
+ bit 2,[hl] ; dungeon warp or fly warp?
+ res 2,[hl]
+ jr z,.next
+; if dungeon warp or fly warp
+ ld a,[wDestinationMap]
+ jr .next2
+.next
+ bit 1,[hl]
+ jr z,.next3
+ call EmptyFunc
+.next3
+ ld a,0
+.next2
+ ld b,a
+ ld a,[wd72d]
+ and a
+ jr nz,.next4
+ ld a,b
+.next4
+ ld hl,wd732
+ bit 4,[hl] ; dungeon warp?
+ ret nz
+; if not dungeon warp
+ ld [wLastMap],a
+ ret
+
+; gets the map ID, tile block map view pointer, tileset, and coordinates
+LoadSpecialWarpData: ; 62ff (1:62ff)
+ ld a, [wd72d]
+ cp BATTLE_CENTER
+ jr nz, .notBattleCenter
+ ld hl, BattleCenterSpec1
+ ld a, [hSerialConnectionStatus]
+ cp USING_INTERNAL_CLOCK ; which gameboy is clocking determines who is on the left and who is on the right
+ jr z, .copyWarpData
+ ld hl, BattleCenterSpec2
+ jr .copyWarpData
+.notBattleCenter
+ cp TRADE_CENTER
+ jr nz, .notTradeCenter
+ ld hl, TradeCenterSpec1
+ ld a, [hSerialConnectionStatus]
+ cp USING_INTERNAL_CLOCK
+ jr z, .copyWarpData
+ ld hl, TradeCenterSpec2
+ jr .copyWarpData
+.notTradeCenter
+ ld a, [wd732]
+ bit 1, a
+ jr nz, .notFirstMap
+ bit 2, a
+ jr nz, .notFirstMap
+ ld hl, FirstMapSpec
+.copyWarpData
+ ld de, W_CURMAP
+ ld c, $7
+.copyWarpDataLoop
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .copyWarpDataLoop
+ ld a, [hli]
+ ld [W_CURMAPTILESET], a
+ xor a
+ jr .done
+.notFirstMap
+ ld a, [wLastMap]
+ ld hl, wd732
+ bit 4, [hl] ; used dungeon warp (jumped down hole/waterfall)?
+ jr nz, .usedDunegonWarp
+ bit 6, [hl] ; return to last pokemon center (or player's house)?
+ res 6, [hl]
+ jr z, .otherDestination
+; return to last pokemon center or player's house
+ ld a, [wLastBlackoutMap]
+ jr .usedFlyWarp
+.usedDunegonWarp
+ ld hl, wd72d
+ res 4, [hl]
+ ld a, [wDungeonWarpDestinationMap]
+ ld b, a
+ ld [W_CURMAP], a
+ ld a, [wWhichDungeonWarp]
+ ld c, a
+ ld hl, DungeonWarpList
+ ld de, $0
+ ld a, $6
+ ld [wd12f], a
+.dungeonWarpListLoop
+ ld a, [hli]
+ cp b
+ jr z, .matchedDungeonWarpDestinationMap
+ inc hl
+ jr .nextDungeonWarp
+.matchedDungeonWarpDestinationMap
+ ld a, [hli]
+ cp c
+ jr z, .matchedDungeonWarpID
+.nextDungeonWarp
+ ld a, [wd12f]
+ add e
+ ld e, a
+ jr .dungeonWarpListLoop
+.matchedDungeonWarpID
+ ld hl, DungeonWarpData
+ add hl, de
+ jr .copyWarpData2
+.otherDestination
+ ld a, [wDestinationMap]
+.usedFlyWarp
+ ld b, a
+ ld [W_CURMAP], a
+ ld hl, FlyWarpDataPtr
+.flyWarpDataPtrLoop
+ ld a, [hli]
+ inc hl
+ cp b
+ jr z, .foundFlyWarpMatch
+ inc hl
+ inc hl
+ jr .flyWarpDataPtrLoop
+.foundFlyWarpMatch
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+.copyWarpData2
+ ld de, wCurrentTileBlockMapViewPointer
+ ld c, $6
+.copyWarpDataLoop2
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .copyWarpDataLoop2
+ xor a ; OVERWORLD
+ ld [W_CURMAPTILESET], a
+.done
+ ld [wYOffsetSinceLastSpecialWarp], a
+ ld [wXOffsetSinceLastSpecialWarp], a
+ ld a, $ff ; the player's coordinates have already been updated using a special warp, so don't use any of the normal warps
+ ld [wDestinationWarpID], a
+ ret
+
+INCLUDE "data/special_warps.asm"
+
+; This function appears to never be used.
+; It is likely a debugging feature to give the player Tsunekazu Ishihara's
+; favorite Pokemon. This is indicated by the overpowered Exeggutor, which
+; Ishihara (president of Creatures Inc.) said was his favorite Pokemon in an ABC
+; interview on February 8, 2000.
+; "Exeggutor is my favorite. That's because I was always using this character
+; while I was debugging the program."
+; http://www.ign.com/articles/2000/02/09/abc-news-pokamon-chat-transcript
+
+SetIshiharaTeam: ; 64ca (1:64ca)
+ ld de, IshiharaTeam
+.loop
+ ld a, [de]
+ cp $ff
+ ret z
+ ld [wcf91], a
+ inc de
+ ld a, [de]
+ ld [W_CURENEMYLVL], a
+ inc de
+ call AddPartyMon
+ jr .loop
+
+IshiharaTeam: ; 64df (1:64df)
+ db EXEGGUTOR,90
+ db MEW,20
+ db JOLTEON,56
+ db DUGTRIO,56
+ db ARTICUNO,57
+ db $FF
+
+EmptyFunc: ; 64ea (1:64ea)
+ ret
+
+INCLUDE "engine/menu/naming_screen.asm"
+
+INCLUDE "engine/oak_speech2.asm"
+
+; subtracts the amount the player paid from their money
+; sets carry flag if there is enough money and unsets carry flag if not
+SubtractAmountPaidFromMoney_: ; 6b21 (1:6b21)
+ ld de,wPlayerMoney
+ ld hl,$ff9f ; total price of items
+ ld c,3 ; length of money in bytes
+ call StringCmp
+ ret c
+ ld de,wPlayerMoney + 2
+ ld hl,$ffa1 ; total price of items
+ ld c,3 ; length of money in bytes
+ predef SubBCDPredef ; subtract total price from money
+ ld a,MONEY_BOX
+ ld [wTextBoxID],a
+ call DisplayTextBoxID ; redraw money text box
+ and a
+ ret
+
+HandleItemListSwapping: ; 6b44 (1:6b44)
+ ld a,[wListMenuID]
+ cp a,ITEMLISTMENU
+ jp nz,DisplayListMenuIDLoop ; only rearrange item list menus
+ push hl
+ ld hl,wList
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ inc hl ; hl = beginning of list entries
+ ld a,[wCurrentMenuItem]
+ ld b,a
+ ld a,[wListScrollOffset]
+ add b
+ add a
+ ld c,a
+ ld b,0
+ add hl,bc ; hl = address of currently selected item entry
+ ld a,[hl]
+ pop hl
+ inc a
+ jp z,DisplayListMenuIDLoop ; ignore attempts to swap the Cancel menu item
+ ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ and a ; has the first item to swap already been chosen?
+ jr nz,.swapItems
+; if not, set the currently selected item as the first item
+ ld a,[wCurrentMenuItem]
+ inc a
+ ld b,a
+ ld a,[wListScrollOffset] ; index of top (visible) menu item within the list
+ add b
+ ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1)
+ ld c,20
+ call DelayFrames
+ jp DisplayListMenuIDLoop
+.swapItems
+ ld a,[wCurrentMenuItem]
+ inc a
+ ld b,a
+ ld a,[wListScrollOffset]
+ add b
+ ld b,a
+ ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ cp b ; is the currently selected item the same as the first item to swap?
+ jp z,DisplayListMenuIDLoop ; ignore attempts to swap an item with itself
+ dec a
+ ld [wMenuItemToSwap],a ; ID of item chosen for swapping (counts from 1)
+ ld c,20
+ call DelayFrames
+ push hl
+ push de
+ ld hl,wList
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ inc hl ; hl = beginning of list entries
+ ld d,h
+ ld e,l ; de = beginning of list entries
+ ld a,[wCurrentMenuItem]
+ ld b,a
+ ld a,[wListScrollOffset]
+ add b
+ add a
+ ld c,a
+ ld b,0
+ add hl,bc ; hl = address of currently selected item entry
+ ld a,[wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ add a
+ add e
+ ld e,a
+ jr nc,.noCarry
+ inc d
+.noCarry ; de = address of first item to swap
+ ld a,[de]
+ ld b,a
+ ld a,[hli]
+ cp b
+ jr z,.swapSameItemType
+.swapDifferentItems
+ ld [$ff95],a ; [$ff95] = second item ID
+ ld a,[hld]
+ ld [$ff96],a ; [$ff96] = second item quantity
+ ld a,[de]
+ ld [hli],a ; put first item ID in second item slot
+ inc de
+ ld a,[de]
+ ld [hl],a ; put first item quantity in second item slot
+ ld a,[$ff96]
+ ld [de],a ; put second item quantity in first item slot
+ dec de
+ ld a,[$ff95]
+ ld [de],a ; put second item ID in first item slot
+ xor a
+ ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped
+ pop de
+ pop hl
+ jp DisplayListMenuIDLoop
+.swapSameItemType
+ inc de
+ ld a,[hl]
+ ld b,a
+ ld a,[de]
+ add b ; a = sum of both item quantities
+ cp a,100 ; is the sum too big for one item slot?
+ jr c,.combineItemSlots
+; swap enough items from the first slot to max out the second slot if they can't be combined
+ sub a,99
+ ld [de],a
+ ld a,99
+ ld [hl],a
+ jr .done
+.combineItemSlots
+ ld [hl],a ; put the sum in the second item slot
+ ld hl,wList
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ dec [hl] ; decrease the number of items
+ ld a,[hl]
+ ld [wd12a],a ; update number of items variable
+ cp a,1
+ jr nz,.skipSettingMaxMenuItemID
+ ld [wMaxMenuItem],a ; if the number of items is only one now, update the max menu item ID
+.skipSettingMaxMenuItemID
+ dec de
+ ld h,d
+ ld l,e
+ inc hl
+ inc hl ; hl = address of item after first item to swap
+.moveItemsUpLoop ; erase the first item slot and move up all the following item slots to fill the gap
+ ld a,[hli]
+ ld [de],a
+ inc de
+ inc a ; reached the $ff terminator?
+ jr z,.afterMovingItemsUp
+ ld a,[hli]
+ ld [de],a
+ inc de
+ jr .moveItemsUpLoop
+.afterMovingItemsUp
+ xor a
+ ld [wListScrollOffset],a
+ ld [wCurrentMenuItem],a
+.done
+ xor a
+ ld [wMenuItemToSwap],a ; 0 means no item is currently being swapped
+ pop de
+ pop hl
+ jp DisplayListMenuIDLoop
+
+INCLUDE "engine/overworld/pokemart.asm"
+
+INCLUDE "engine/learn_move.asm"
+
+INCLUDE "engine/overworld/pokecenter.asm"
+
+SetLastBlackoutMap:
+; Set the map to return to when
+; blacking out or using Teleport or Dig.
+; Safari rest houses don't count.
+
+ push hl
+ ld hl, SafariZoneRestHouses
+ ld a, [W_CURMAP]
+ ld b, a
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .notresthouse
+ cp b
+ jr nz, .loop
+ jr .done
+
+.notresthouse
+ ld a, [wLastMap]
+ ld [wLastBlackoutMap], a
+.done
+ pop hl
+ ret
+
+SafariZoneRestHouses:
+ db SAFARI_ZONE_REST_HOUSE_2
+ db SAFARI_ZONE_REST_HOUSE_3
+ db SAFARI_ZONE_REST_HOUSE_4
+ db -1
+
+; function that performs initialization for DisplayTextID
+DisplayTextIDInit: ; 7096 (1:7096)
+ xor a
+ ld [wListMenuID],a
+ ld a,[wAutoTextBoxDrawingControl]
+ bit 0,a
+ jr nz,.skipDrawingTextBoxBorder
+ ld a,[$ff8c] ; text ID (or sprite ID)
+ and a
+ jr nz,.notStartMenu
+; if text ID is 0 (i.e. the start menu)
+; Note that the start menu text border is also drawn in the function directly
+; below this, so this seems unnecessary.
+ ld a,[wd74b]
+ bit 5,a ; does the player have the pokedex?
+; start menu with pokedex
+ hlCoord 10, 0
+ ld b,$0e
+ ld c,$08
+ jr nz,.drawTextBoxBorder
+; start menu without pokedex
+ hlCoord 10, 0
+ ld b,$0c
+ ld c,$08
+ jr .drawTextBoxBorder
+; if text ID is not 0 (i.e. not the start menu) then do a standard dialogue text box
+.notStartMenu
+ hlCoord 0, 12
+ ld b,$04
+ ld c,$12
+.drawTextBoxBorder
+ call TextBoxBorder
+.skipDrawingTextBoxBorder
+ ld hl,wFontLoaded
+ set 0,[hl]
+ ld hl,wFlags_0xcd60
+ bit 4,[hl]
+ res 4,[hl]
+ jr nz,.skipMovingSprites
+ call UpdateSprites ; move sprites
+.skipMovingSprites
+; loop to copy C1X9 (direction the sprite is facing) to C2X9 for each sprite
+; this is done because when you talk to an NPC, they turn to look your way
+; the original direction they were facing must be restored after the dialogue is over
+ ld hl,wSpriteStateData1 + $19
+ ld c,$0f
+ ld de,$0010
+.spriteFacingDirectionCopyLoop
+ ld a,[hl]
+ inc h
+ ld [hl],a
+ dec h
+ add hl,de
+ dec c
+ jr nz,.spriteFacingDirectionCopyLoop
+; loop to force all the sprites in the middle of animation to stand still
+; (so that they don't like they're frozen mid-step during the dialogue)
+ ld hl,wSpriteStateData1 + 2
+ ld de,$0010
+ ld c,e
+.spriteStandStillLoop
+ ld a,[hl]
+ cp a,$ff ; is the sprite visible?
+ jr z,.nextSprite
+; if it is visible
+ and a,$fc
+ ld [hl],a
+.nextSprite
+ add hl,de
+ dec c
+ jr nz,.spriteStandStillLoop
+ ld b,$9c ; window background address
+ call CopyScreenTileBufferToVRAM ; transfer background in WRAM to VRAM
+ xor a
+ ld [hWY],a ; put the window on the screen
+ call LoadFontTilePatterns
+ ld a,$01
+ ld [H_AUTOBGTRANSFERENABLED],a ; enable continuous WRAM to VRAM transfer each V-blank
+ ret
+
+; function that displays the start menu
+DrawStartMenu: ; 710b (1:710b)
+ ld a,[wd74b]
+ bit 5,a ; does the player have the pokedex?
+; menu with pokedex
+ hlCoord 10, 0
+ ld b,$0e
+ ld c,$08
+ jr nz,.drawTextBoxBorder
+; shorter menu if the player doesn't have the pokedex
+ hlCoord 10, 0
+ ld b,$0c
+ ld c,$08
+.drawTextBoxBorder
+ call TextBoxBorder
+ ld a,%11001011 ; bit mask for down, up, start, B, and A buttons
+ ld [wMenuWatchedKeys],a
+ ld a,$02
+ ld [wTopMenuItemY],a ; Y position of first menu choice
+ ld a,$0b
+ ld [wTopMenuItemX],a ; X position of first menu choice
+ ld a,[wcc2d] ; remembered menu selection from last time
+ ld [wCurrentMenuItem],a
+ ld [wLastMenuItem],a
+ xor a
+ ld [wcc37],a
+ ld hl,wd730
+ set 6,[hl] ; no pauses between printing each letter
+ hlCoord 12, 2
+ ld a,[wd74b]
+ bit 5,a ; does the player have the pokedex?
+; case for not having pokdex
+ ld a,$06
+ jr z,.storeMenuItemCount
+; case for having pokedex
+ ld de,StartMenuPokedexText
+ call PrintStartMenuItem
+ ld a,$07
+.storeMenuItemCount
+ ld [wMaxMenuItem],a ; number of menu items
+ ld de,StartMenuPokemonText
+ call PrintStartMenuItem
+ ld de,StartMenuItemText
+ call PrintStartMenuItem
+ ld de,wPlayerName ; player's name
+ call PrintStartMenuItem
+ ld a,[wd72e]
+ bit 6,a ; is the player using the link feature?
+; case for not using link feature
+ ld de,StartMenuSaveText
+ jr z,.printSaveOrResetText
+; case for using link feature
+ ld de,StartMenuResetText
+.printSaveOrResetText
+ call PrintStartMenuItem
+ ld de,StartMenuOptionText
+ call PrintStartMenuItem
+ ld de,StartMenuExitText
+ call PlaceString
+ ld hl,wd730
+ res 6,[hl] ; turn pauses between printing letters back on
+ ret
+
+StartMenuPokedexText: ; 718f (1:718f)
+ db "POKéDEX@"
+
+StartMenuPokemonText: ; 7197 (1:7197)
+ db "POKéMON@"
+
+StartMenuItemText: ; 719f (1:719f)
+ db "ITEM@"
+
+StartMenuSaveText: ; 71a4 (1:71a4)
+ db "SAVE@"
+
+StartMenuResetText: ; 71a9 (1:71a9)
+ db "RESET@"
+
+StartMenuExitText: ; 71af (1:71af)
+ db "EXIT@"
+
+StartMenuOptionText: ; 71b4 (1:71b4)
+ db "OPTION@"
+
+PrintStartMenuItem: ; 71bb (1:71bb)
+ push hl
+ call PlaceString
+ pop hl
+ ld de,$28
+ add hl,de
+ ret
+
+INCLUDE "engine/overworld/cable_club_npc.asm"
+
+; function to draw various text boxes
+DisplayTextBoxID_: ; 72ea (1:72ea)
+ ld a,[wTextBoxID]
+ cp a,TWO_OPTION_MENU
+ jp z,DisplayTwoOptionMenu
+ ld c,a
+ ld hl,TextBoxFunctionTable
+ ld de,3
+ call SearchTextBoxTable
+ jr c,.functionTableMatch
+ ld hl,TextBoxCoordTable
+ ld de,5
+ call SearchTextBoxTable
+ jr c,.coordTableMatch
+ ld hl,TextBoxTextAndCoordTable
+ ld de,9
+ call SearchTextBoxTable
+ jr c,.textAndCoordTableMatch
+.done
+ ret
+.functionTableMatch
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a ; hl = address of function
+ ld de,.done
+ push de
+ jp [hl] ; jump to the function
+.coordTableMatch
+ call GetTextBoxIDCoords
+ call GetAddressOfScreenCoords
+ call TextBoxBorder
+ ret
+.textAndCoordTableMatch
+ call GetTextBoxIDCoords
+ push hl
+ call GetAddressOfScreenCoords
+ call TextBoxBorder
+ pop hl
+ call GetTextBoxIDText
+ ld a,[wd730]
+ push af
+ ld a,[wd730]
+ set 6,a ; no pauses between printing each letter
+ ld [wd730],a
+ call PlaceString
+ pop af
+ ld [wd730],a
+ call UpdateSprites ; move sprites
+ ret
+
+; function to search a table terminated with $ff for a byte matching c in increments of de
+; sets carry flag if a match is found and clears carry flag if not
+SearchTextBoxTable: ; 734c (1:734c)
+ dec de
+.loop
+ ld a,[hli]
+ cp a,$ff
+ jr z,.notFound
+ cp c
+ jr z,.found
+ add hl,de
+ jr .loop
+.found
+ scf
+.notFound
+ ret
+
+; function to load coordinates from the TextBoxCoordTable or the TextBoxTextAndCoordTable
+; INPUT:
+; hl = address of coordinates
+; OUTPUT:
+; b = height
+; c = width
+; d = row of upper left corner
+; e = column of upper left corner
+GetTextBoxIDCoords: ; 735a (1:735a)
+ ld a,[hli] ; column of upper left corner
+ ld e,a
+ ld a,[hli] ; row of upper left corner
+ ld d,a
+ ld a,[hli] ; column of lower right corner
+ sub e
+ dec a
+ ld c,a ; c = width
+ ld a,[hli] ; row of lower right corner
+ sub d
+ dec a
+ ld b,a ; b = height
+ ret
+
+; function to load a text address and text coordinates from the TextBoxTextAndCoordTable
+GetTextBoxIDText: ; 7367 (1:7367)
+ ld a,[hli]
+ ld e,a
+ ld a,[hli]
+ ld d,a ; de = address of text
+ push de ; save text address
+ ld a,[hli]
+ ld e,a ; column of upper left corner of text
+ ld a,[hl]
+ ld d,a ; row of upper left corner of text
+ call GetAddressOfScreenCoords
+ pop de ; restore text address
+ ret
+
+; function to point hl to the screen coordinates
+; INPUT:
+; d = row
+; e = column
+; OUTPUT:
+; hl = address of upper left corner of text box
+GetAddressOfScreenCoords: ; 7375 (1:7375)
+ push bc
+ ld hl,wTileMap
+ ld bc,20
+.loop ; loop to add d rows to the base address
+ ld a,d
+ and a
+ jr z,.addedRows
+ add hl,bc
+ dec d
+ jr .loop
+.addedRows
+ pop bc
+ add hl,de
+ ret
+
+; Format:
+; 00: text box ID
+; 01-02: function address
+TextBoxFunctionTable: ; 7387 (1:7387)
+ dbw MONEY_BOX, DisplayMoneyBox
+ dbw BUY_SELL_QUIT_MENU, DoBuySellQuitMenu
+ dbw FIELD_MOVE_MON_MENU, DisplayFieldMoveMonMenu
+ db $ff ; terminator
+
+; Format:
+; 00: text box ID
+; 01: column of upper left corner
+; 02: row of upper left corner
+; 03: column of lower right corner
+; 04: row of lower right corner
+TextBoxCoordTable: ; 7391 (1:7391)
+ db MESSAGE_BOX, 0, 12, 19, 17
+ db $03, 0, 0, 19, 14
+ db $07, 0, 0, 11, 6
+ db LIST_MENU_BOX, 4, 2, 19, 12
+ db $10, 7, 0, 19, 17
+ db MON_SPRITE_POPUP, 6, 4, 14, 13
+ db $ff ; terminator
+
+; Format:
+; 00: text box ID
+; 01: column of upper left corner
+; 02: row of upper left corner
+; 03: column of lower right corner
+; 04: row of lower right corner
+; 05-06: address of text
+; 07: column of beginning of text
+; 08: row of beginning of text
+; table of window positions and corresponding text [key, start column, start row, end column, end row, text pointer [2 bytes], text column, text row]
+TextBoxTextAndCoordTable: ; 73b0 (1:73b0)
+ db JP_MOCHIMONO_MENU_TEMPLATE
+ db 0,0,14,17 ; text box coordinates
+ dw JapaneseMochimonoText
+ db 3,0 ; text coordinates
+
+ db USE_TOSS_MENU_TEMPLATE
+ db 13,10,19,14 ; text box coordinates
+ dw UseTossText
+ db 15,11 ; text coordinates
+
+ db JP_SAVE_MESSAGE_MENU_TEMPLATE
+ db 0,0,7,5 ; text box coordinates
+ dw JapaneseSaveMessageText
+ db 2,2 ; text coordinates
+
+ db JP_SPEED_OPTIONS_MENU_TEMPLATE
+ db 0,6,5,10 ; text box coordinates
+ dw JapaneseSpeedOptionsText
+ db 2,7 ; text coordinates
+
+ db BATTLE_MENU_TEMPLATE
+ db 8,12,19,17 ; text box coordinates
+ dw BattleMenuText
+ db 10,14 ; text coordinates
+
+ db SAFARI_BATTLE_MENU_TEMPLATE
+ db 0,12,19,17 ; text box coordinates
+ dw SafariZoneBattleMenuText
+ db 2,14 ; text coordinates
+
+ db SWITCH_STATS_CANCEL_MENU_TEMPLATE
+ db 11,11,19,17 ; text box coordinates
+ dw SwitchStatsCancelText
+ db 13,12 ; text coordinates
+
+ db BUY_SELL_QUIT_MENU_TEMPLATE
+ db 0,0,10,6 ; text box coordinates
+ dw BuySellQuitText
+ db 2,1 ; text coordinates
+
+ db MONEY_BOX_TEMPLATE
+ db 11,0,19,2 ; text box coordinates
+ dw MoneyText
+ db 13,0 ; text coordinates
+
+ db JP_AH_MENU_TEMPLATE
+ db 7,6,11,10 ; text box coordinates
+ dw JapaneseAhText
+ db 8,8 ; text coordinates
+
+ db JP_POKEDEX_MENU_TEMPLATE
+ db 11,8,19,17 ; text box coordinates
+ dw JapanesePokedexMenu
+ db 12,10 ; text coordinates
+
+; note that there is no terminator
+
+BuySellQuitText: ; 7413 (1:7413)
+ db "BUY"
+ next "SELL"
+ next "QUIT@@"
+
+UseTossText: ; 7422 (1:7422)
+ db "USE"
+ next "TOSS@"
+
+JapaneseSaveMessageText: ; 742b (1:742b)
+ db "きろく"
+ next "メッセージ@"
+
+JapaneseSpeedOptionsText: ; 7435 (1:7435)
+ db "はやい"
+ next "おそい@"
+
+MoneyText: ; 743d (1:743d)
+ db "MONEY@"
+
+JapaneseMochimonoText: ; 7443 (1:7443)
+ db "もちもの@"
+
+JapaneseMainMenuText: ; 7448 (1:7448)
+ db "つづきから"
+ next "さいしょから@"
+
+BattleMenuText: ; 7455 (1:7455)
+ db "FIGHT ",$E1,$E2
+ next "ITEM RUN@"
+
+SafariZoneBattleMenuText: ; 7468 (1:7468)
+ db "BALL× BAIT"
+ next "THROW ROCK RUN@"
+
+SwitchStatsCancelText: ; 7489 (1:7489)
+ db "SWITCH"
+ next "STATS"
+ next "CANCEL@"
+
+JapaneseAhText: ; 749d (1:749d)
+ db "アッ!@"
+
+JapanesePokedexMenu: ; 74a1 (1:74a1)
+ db "データをみる"
+ next "なきごえ"
+ next "ぶんぷをみる"
+ next "キャンセル@"
+
+DisplayMoneyBox: ; 74ba (1:74ba)
+ ld hl, wd730
+ set 6, [hl]
+ ld a, MONEY_BOX_TEMPLATE
+ ld [wTextBoxID], a
+ call DisplayTextBoxID
+ hlCoord 13, 1
+ ld b, $1
+ ld c, $6
+ call ClearScreenArea
+ hlCoord 12, 1
+ ld de, wPlayerMoney
+ ld c, $a3
+ call PrintBCDNumber
+ ld hl, wd730
+ res 6, [hl]
+ ret
+
+CurrencyString: ; 74e2 (1:74e2)
+ db " ¥@"
+
+DoBuySellQuitMenu: ; 74ea (1:74ea)
+ ld a, [wd730]
+ set 6, a ; no printing delay
+ ld [wd730], a
+ xor a
+ ld [wd12d], a
+ ld a, BUY_SELL_QUIT_MENU_TEMPLATE
+ ld [wTextBoxID], a
+ call DisplayTextBoxID
+ ld a, A_BUTTON | B_BUTTON
+ ld [wMenuWatchedKeys], a
+ ld a, $2
+ ld [wMaxMenuItem], a
+ ld a, $1
+ ld [wTopMenuItemY], a
+ ld a, $1
+ ld [wTopMenuItemX], a
+ xor a
+ ld [wCurrentMenuItem], a
+ ld [wLastMenuItem], a
+ ld [wcc37], a
+ ld a, [wd730]
+ res 6, a ; turn on the printing delay
+ ld [wd730], a
+ call HandleMenuInput
+ call PlaceUnfilledArrowMenuCursor
+ bit 0, a ; was A pressed?
+ jr nz, .pressedA
+ bit 1, a ; was B pressed? (always true since only A/B are watched)
+ jr z, .pressedA
+ ld a, $2
+ ld [wd12e], a
+ jr .quit
+.pressedA
+ ld a, $1
+ ld [wd12e], a
+ ld a, [wCurrentMenuItem]
+ ld [wd12d], a
+ ld b, a
+ ld a, [wMaxMenuItem]
+ cp b
+ jr z, .quit
+ ret
+.quit
+ ld a, $2
+ ld [wd12e], a
+ ld a, [wCurrentMenuItem]
+ ld [wd12d], a
+ scf
+ ret
+
+; displays a menu with two options to choose from
+; b = Y of upper left corner of text region
+; c = X of upper left corner of text region
+; hl = address where the text box border should be drawn
+DisplayTwoOptionMenu: ; 7559 (1:7559)
+ push hl
+ ld a, [wd730]
+ set 6, a ; no printing delay
+ ld [wd730], a
+ xor a
+ ld [wd12d], a
+ ld [wd12e], a
+ ld a, A_BUTTON | B_BUTTON
+ ld [wMenuWatchedKeys], a
+ ld a, $1
+ ld [wMaxMenuItem], a
+ ld a, b
+ ld [wTopMenuItemY], a
+ ld a, c
+ ld [wTopMenuItemX], a
+ xor a
+ ld [wLastMenuItem], a
+ ld [wcc37], a
+ push hl
+ ld hl, wTwoOptionMenuID
+ bit 7, [hl] ; select second menu item by default?
+ res 7, [hl]
+ jr z, .storeCurrentMenuItem
+ inc a
+.storeCurrentMenuItem
+ ld [wCurrentMenuItem], a
+ pop hl
+ push hl
+ push hl
+ call TwoOptionMenu_SaveScreenTiles
+ ld a, [wTwoOptionMenuID]
+ ld hl, TwoOptionMenuStrings
+ ld e, a
+ ld d, $0
+ ld a, $5
+.menuStringLoop
+ add hl, de
+ dec a
+ jr nz, .menuStringLoop
+ ld a, [hli]
+ ld c, a
+ ld a, [hli]
+ ld b, a
+ ld e, l
+ ld d, h
+ pop hl
+ push de
+ ld a, [wTwoOptionMenuID]
+ cp TRADE_CANCEL_MENU
+ jr nz, .notTradeCancelMenu
+ call CableClub_TextBoxBorder
+ jr .afterTextBoxBorder
+.notTradeCancelMenu
+ call TextBoxBorder
+.afterTextBoxBorder
+ call UpdateSprites
+ pop hl
+ ld a, [hli]
+ and a ; put blank line before first menu item?
+ ld bc, 20 + 2
+ jr z, .noBlankLine
+ ld bc, 2 * 20 + 2
+.noBlankLine
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ pop hl
+ add hl, bc
+ call PlaceString
+ ld hl, wd730
+ res 6, [hl] ; turn on the printing delay
+ ld a, [wTwoOptionMenuID]
+ cp NO_YES_MENU
+ jr nz, .notNoYesMenu
+; No/Yes menu
+; this menu type ignores the B button
+; it only seems to be used when confirming the deletion of a save file
+ xor a
+ ld [wTwoOptionMenuID], a
+ ld a, [wFlags_0xcd60]
+ push af
+ push hl
+ ld hl, wFlags_0xcd60
+ bit 5, [hl]
+ set 5, [hl] ; don't play sound when A or B is pressed in menu
+ pop hl
+.noYesMenuInputLoop
+ call HandleMenuInput
+ bit 1, a ; A button pressed?
+ jr nz, .noYesMenuInputLoop ; try again if A was not pressed
+ pop af
+ pop hl
+ ld [wFlags_0xcd60], a
+ ld a, (SFX_02_40 - SFX_Headers_02) / 3
+ call PlaySound
+ jr .pressedAButton
+.notNoYesMenu
+ xor a
+ ld [wTwoOptionMenuID], a
+ call HandleMenuInput
+ pop hl
+ bit 1, a ; A button pressed?
+ jr nz, .choseSecondMenuItem ; automatically choose the second option if B is pressed
+.pressedAButton
+ ld a, [wCurrentMenuItem]
+ ld [wd12d], a
+ and a
+ jr nz, .choseSecondMenuItem
+; chose first menu item
+ ld a, $1
+ ld [wd12e], a
+ ld c, 15
+ call DelayFrames
+ call TwoOptionMenu_RestoreScreenTiles
+ and a
+ ret
+.choseSecondMenuItem
+ ld a, $1
+ ld [wCurrentMenuItem], a
+ ld [wd12d], a
+ ld a, $2
+ ld [wd12e], a
+ ld c, 15
+ call DelayFrames
+ call TwoOptionMenu_RestoreScreenTiles
+ scf
+ ret
+
+; Some of the wider/taller two option menus will not have the screen areas
+; they cover be fully saved/restored by the two functions below.
+; The bottom and right edges of the menu may remain after the function returns.
+
+TwoOptionMenu_SaveScreenTiles: ; 763e (1:763e)
+ ld de, wHPBarMaxHP
+ ld bc, $506
+.asm_7644
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .asm_7644
+ push bc
+ ld bc, 14
+ add hl, bc
+ pop bc
+ ld c, $6
+ dec b
+ jr nz, .asm_7644
+ ret
+
+TwoOptionMenu_RestoreScreenTiles: ; 7656 (1:7656)
+ ld de, wHPBarMaxHP
+ ld bc, $506
+.asm_765c
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec c
+ jr nz, .asm_765c
+ push bc
+ ld bc, $e
+ add hl, bc
+ pop bc
+ ld c, $6
+ dec b
+ jr nz, .asm_765c
+ call UpdateSprites
+ ret
+
+; Format:
+; 00: byte width
+; 01: byte height
+; 02: byte put blank line before first menu item
+; 03: word text pointer
+TwoOptionMenuStrings: ; 7671 (1:7671)
+ db 4,3,0
+ dw .YesNoMenu
+ db 6,3,0
+ dw .NorthWestMenu
+ db 6,3,0
+ dw .SouthEastMenu
+ db 6,3,0
+ dw .YesNoMenu
+ db 6,3,0
+ dw .NorthEastMenu
+ db 7,3,0
+ dw .TradeCancelMenu
+ db 7,4,1
+ dw .HealCancelMenu
+ db 4,3,0
+ dw .NoYesMenu
+
+.NoYesMenu ; 7699 (1:3699)
+ db "NO",$4E,"YES@"
+.YesNoMenu ; 76a0 (1:36a0)
+ db "YES",$4E,"NO@"
+.NorthWestMenu ; 76a7 (1:36a7)
+ db "NORTH",$4E,"WEST@"
+.SouthEastMenu ; 76b2 (1:36b2)
+ db "SOUTH",$4E,"EAST@"
+.NorthEastMenu ; 76bd (1:36bd)
+ db "NORTH",$4E,"EAST@"
+.TradeCancelMenu ; 76c8 (1:36c8)
+ db "TRADE",$4E,"CANCEL@"
+.HealCancelMenu ; 76d5 (1:36d5)
+ db "HEAL",$4E,"CANCEL@"
+
+DisplayFieldMoveMonMenu: ; 76e1 (1:36e1)
+ xor a
+ ld hl, wWhichTrade
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], $c
+ call GetMonFieldMoves
+ ld a, [wTrainerScreenX]
+ and a
+ jr nz, .asm_770f
+ hlCoord 11, 11
+ ld b, $5
+ ld c, $7
+ call TextBoxBorder
+ call UpdateSprites
+ ld a, $c
+ ld [$fff7], a
+ hlCoord 13, 12
+ ld de, PokemonMenuEntries
+ jp PlaceString
+.asm_770f
+ push af
+ hlCoord 0, 11
+ ld a, [wcd42]
+ dec a
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld b, $5
+ ld a, $12
+ sub e
+ ld c, a
+ pop af
+ ld de, $ffd8
+.asm_7725
+ add hl, de
+ inc b
+ inc b
+ dec a
+ jr nz, .asm_7725
+ ld de, $ffec
+ add hl, de
+ inc b
+ call TextBoxBorder
+ call UpdateSprites
+ hlCoord 0, 12
+ ld a, [wcd42]
+ inc a
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld de, $ffd8
+ ld a, [wTrainerScreenX]
+.asm_7747
+ add hl, de
+ dec a
+ jr nz, .asm_7747
+ xor a
+ ld [wTrainerScreenX], a
+ ld de, wWhichTrade
+.asm_7752
+ push hl
+ ld hl, FieldMoveNames
+ ld a, [de]
+ and a
+ jr z, .asm_7776
+ inc de
+ ld b, a
+.asm_775c
+ dec b
+ jr z, .asm_7766
+.asm_775f
+ ld a, [hli]
+ cp $50
+ jr nz, .asm_775f
+ jr .asm_775c
+.asm_7766
+ ld b, h
+ ld c, l
+ pop hl
+ push de
+ ld d, b
+ ld e, c
+ call PlaceString
+ ld bc, $28
+ add hl, bc
+ pop de
+ jr .asm_7752
+.asm_7776
+ pop hl
+ ld a, [wcd42]
+ ld [$fff7], a
+ hlCoord 0, 12
+ ld a, [wcd42]
+ inc a
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld de, PokemonMenuEntries
+ jp PlaceString
+
+FieldMoveNames: ; 778d (1:778d)
+ db "CUT@"
+ db "FLY@"
+ db "@"
+ db "SURF@"
+ db "STRENGTH@"
+ db "FLASH@"
+ db "DIG@"
+ db "TELEPORT@"
+ db "SOFTBOILED@"
+
+PokemonMenuEntries: ; 77c2 (1:77c2)
+ db "STATS"
+ next "SWITCH"
+ next "CANCEL@"
+
+GetMonFieldMoves: ; 77d6 (1:77d6)
+ ld a, [wWhichPokemon]
+ ld hl, wPartyMon1Moves
+ ld bc, $2c
+ call AddNTimes
+ ld d, h
+ ld e, l
+ ld c, $5
+ ld hl, wWhichTrade
+.asm_77e9
+ push hl
+.asm_77ea
+ dec c
+ jr z, .asm_7821
+ ld a, [de] ; de is RAM address of move
+ and a
+ jr z, .asm_7821
+ ld b, a
+ inc de ; go to next move
+ ld hl, FieldMoveDisplayData
+.asm_77f6
+ ld a, [hli]
+ cp $ff
+ jr z, .asm_77ea
+ cp b
+ jr z, .asm_7802
+ inc hl
+ inc hl
+ jr .asm_77f6
+.asm_7802
+ ld a, b
+ ld [wcd43], a
+ ld a, [hli]
+ ld b, [hl]
+ pop hl
+ ld [hli], a
+ ld a, [wTrainerScreenX]
+ inc a
+ ld [wTrainerScreenX], a
+ ld a, [wcd42]
+ cp b
+ jr c, .asm_781b
+ ld a, b
+ ld [wcd42], a
+.asm_781b
+ ld a, [wcd43]
+ ld b, a
+ jr .asm_77e9
+.asm_7821
+ pop hl
+ ret
+
+; Format: [Move id], [list priority], [leftmost tile]
+; Move id = id of move
+; List priority = lower number means higher priority when field moves are displayed
+; these priorities must be unique
+; Leftmost tile = -1 + tile column in which the first letter of the move's name should be displayed
+; "SOFTBOILED" is $08 because it has 4 more letters than "SURF", for example, whose value is $0C
+FieldMoveDisplayData: ; 7823 (1:7823)
+ db CUT, $01, $0C
+ db FLY, $02, $0C
+ db $B4, $03, $0C ; unused field move
+ db SURF, $04, $0C
+ db STRENGTH, $05, $0A
+ db FLASH, $06, $0C
+ db DIG, $07, $0C
+ db TELEPORT, $08, $0A
+ db SOFTBOILED, $09, $08
+ db $ff ; list terminator
+
+
+INCLUDE "engine/battle/moveEffects/drain_hp_effect.asm"
+
+INCLUDE "engine/menu/players_pc.asm"
+
+_RemovePokemon: ; 7b68 (1:7b68)
+ ld hl, wPartyCount ; wPartyCount
+ ld a, [wcf95]
+ and a
+ jr z, .asm_7b74
+ ld hl, W_NUMINBOX ; wda80
+.asm_7b74
+ ld a, [hl]
+ dec a
+ ld [hli], a
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld e, l
+ ld d, h
+ inc de
+.asm_7b81
+ ld a, [de]
+ inc de
+ ld [hli], a
+ inc a
+ jr nz, .asm_7b81
+ ld hl, wPartyMonOT ; wd273
+ ld d, $5
+ ld a, [wcf95]
+ and a
+ jr z, .asm_7b97
+ ld hl, wBoxMonOT
+ ld d, $13
+.asm_7b97
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ call SkipFixedLengthTextEntries
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ cp d
+ jr nz, .asm_7ba6
+ ld [hl], $ff
+ ret
+.asm_7ba6
+ ld d, h
+ ld e, l
+ ld bc, $b
+ add hl, bc
+ ld bc, wPartyMonNicks ; wPartyMonNicks
+ ld a, [wcf95]
+ and a
+ jr z, .asm_7bb8
+ ld bc, wBoxMonNicks
+.asm_7bb8
+ call CopyDataUntil
+ ld hl, wPartyMons
+ ld bc, wPartyMon2 - wPartyMon1
+ ld a, [wcf95]
+ and a
+ jr z, .asm_7bcd
+ ld hl, wBoxMons
+ ld bc, wBoxMon2 - wBoxMon1
+.asm_7bcd
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ call AddNTimes
+ ld d, h
+ ld e, l
+ ld a, [wcf95]
+ and a
+ jr z, .asm_7be4
+ ld bc, wBoxMon2 - wBoxMon1
+ add hl, bc
+ ld bc, wBoxMonOT
+ jr .asm_7beb
+.asm_7be4
+ ld bc, wPartyMon2 - wPartyMon1
+ add hl, bc
+ ld bc, wPartyMonOT ; wd273
+.asm_7beb
+ call CopyDataUntil
+ ld hl, wPartyMonNicks ; wPartyMonNicks
+ ld a, [wcf95]
+ and a
+ jr z, .asm_7bfa
+ ld hl, wBoxMonNicks
+.asm_7bfa
+ ld bc, $b
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ call AddNTimes
+ ld d, h
+ ld e, l
+ ld bc, $b
+ add hl, bc
+ ld bc, wPokedexOwned ; wPokedexOwned
+ ld a, [wcf95]
+ and a
+ jr z, .asm_7c15
+ ld bc, wBoxMonNicksEnd
+.asm_7c15
+ jp CopyDataUntil
+
+Func_7c18: ; 7c18 (1:7c18)
+ ld hl, wd730
+ set 6, [hl]
+ predef ShowPokedexData
+ ld hl, wd730
+ res 6, [hl]
+ call ReloadMapData
+ ld c, $a
+ call DelayFrames
+ predef IndexToPokedex
+ ld a, [wd11e]
+ dec a
+ ld c, a
+ ld b, $1
+ ld hl, wPokedexSeen
+ predef FlagActionPredef
+ ld a, $1
+ ld [wDoNotWaitForButtonPressAfterDisplayingText], a
+ ret
+
+
+SECTION "bank3",ROMX,BANK[$3]
+
+INCLUDE "engine/joypad.asm"
+
+INCLUDE "data/map_songs.asm"
+
+INCLUDE "data/map_header_banks.asm"
+
+ClearVariablesAfterLoadingMapData: ; c335 (3:4335)
+ ld a, $90
+ ld [hWY], a
+ ld [rWY], a
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ld [wStepCounter], a
+ ld [W_LONEATTACKNO], a ; W_GYMLEADERNO
+ ld [hJoyPressed], a
+ ld [hJoyReleased], a
+ ld [hJoyHeld], a
+ ld [wcd6a], a
+ ld [wd5a3], a
+ ld hl, wCardKeyDoorY
+ ld [hli], a
+ ld [hl], a
+ ld hl, wWhichTrade
+ ld bc, $1e
+ call FillMemory
+ ret
+
+; only used for setting bit 2 of wd736 upon entering a new map
+IsPlayerStandingOnWarp: ; c35f (3:435f)
+ ld a, [wNumberOfWarps]
+ and a
+ ret z
+ ld c, a
+ ld hl, wWarpEntries
+.loop
+ ld a, [W_YCOORD]
+ cp [hl]
+ jr nz, .nextWarp1
+ inc hl
+ ld a, [W_XCOORD]
+ cp [hl]
+ jr nz, .nextWarp2
+ inc hl
+ ld a, [hli] ; target warp
+ ld [wDestinationWarpID], a
+ ld a, [hl] ; target map
+ ld [$ff8b], a
+ ld hl, wd736
+ set 2, [hl] ; standing on warp flag
+ ret
+.nextWarp1
+ inc hl
+.nextWarp2
+ inc hl
+ inc hl
+ inc hl
+ dec c
+ jr nz, .loop
+ ret
+
+CheckForceBikeOrSurf: ; c38b (3:438b)
+ ld hl, wd732
+ bit 5, [hl]
+ ret nz
+ ld hl, ForcedBikeOrSurfMaps
+ ld a, [W_YCOORD]
+ ld b, a
+ ld a, [W_XCOORD]
+ ld c, a
+ ld a, [W_CURMAP]
+ ld d, a
+.loop
+ ld a, [hli]
+ cp $ff
+ ret z ;if we reach FF then it's not part of the list
+ cp d ;compare to current map
+ jr nz, .incorrectMap
+ ld a, [hli]
+ cp b ;compare y-coord
+ jr nz, .incorrectY
+ ld a, [hli]
+ cp c ;compare x-coord
+ jr nz, .loop ; incorrect x-coord, check next item
+ ld a, [W_CURMAP]
+ cp SEAFOAM_ISLANDS_4
+ ld a, $2
+ ld [W_SEAFOAMISLANDS4CURSCRIPT], a
+ jr z, .forceSurfing
+ ld a, [W_CURMAP]
+ cp SEAFOAM_ISLANDS_5
+ ld a, $2
+ ld [W_SEAFOAMISLANDS5CURSCRIPT], a
+ jr z, .forceSurfing
+ ;force bike riding
+ ld hl, wd732
+ set 5, [hl]
+ ld a, $1
+ ld [wWalkBikeSurfState], a
+ ld [wWalkBikeSurfStateCopy], a
+ jp ForceBikeOrSurf
+.incorrectMap
+ inc hl
+.incorrectY
+ inc hl
+ jr .loop
+.forceSurfing
+ ld a, $2
+ ld [wWalkBikeSurfState], a
+ ld [wWalkBikeSurfStateCopy], a
+ jp ForceBikeOrSurf
+
+INCLUDE "data/force_bike_surf.asm"
+
+IsPlayerFacingEdgeOfMap: ; c3ff (3:43ff)
+ push hl
+ push de
+ push bc
+ ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction
+ srl a
+ ld c, a
+ ld b, $0
+ ld hl, .functionPointerTable
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [W_YCOORD]
+ ld b, a
+ ld a, [W_XCOORD]
+ ld c, a
+ ld de, .asm_c41e
+ push de
+ jp [hl]
+.asm_c41e
+ pop bc
+ pop de
+ pop hl
+ ret
+
+.functionPointerTable
+ dw .facingDown
+ dw .facingUp
+ dw .facingLeft
+ dw .facingRight
+
+.facingDown
+ ld a, [W_CURMAPHEIGHT]
+ add a
+ dec a
+ cp b
+ jr z, .setCarry
+ jr .resetCarry
+
+.facingUp
+ ld a, b
+ and a
+ jr z, .setCarry
+ jr .resetCarry
+
+.facingLeft
+ ld a, c
+ and a
+ jr z, .setCarry
+ jr .resetCarry
+
+.facingRight
+ ld a, [W_CURMAPWIDTH]
+ add a
+ dec a
+ cp c
+ jr z, .setCarry
+ jr .resetCarry
+.resetCarry
+ and a
+ ret
+.setCarry
+ scf
+ ret
+
+IsWarpTileInFrontOfPlayer: ; c44e (3:444e)
+ push hl
+ push de
+ push bc
+ call _GetTileAndCoordsInFrontOfPlayer
+ ld a, [W_CURMAP]
+ cp SS_ANNE_5
+ jr z, .ssAnne5
+ ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction
+ srl a
+ ld c, a
+ ld b, 0
+ ld hl, .warpTileListPointers
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wTileInFrontOfPlayer]
+ ld de, $1
+ call IsInArray
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+.warpTileListPointers: ; c477 (3:4477)
+ dw .facingDownWarpTiles
+ dw .facingUpWarpTiles
+ dw .facingLeftWarpTiles
+ dw .facingRightWarpTiles
+
+.facingDownWarpTiles
+ db $01,$12,$17,$3D,$04,$18,$33,$FF
+
+.facingUpWarpTiles
+ db $01,$5C,$FF
+
+.facingLeftWarpTiles
+ db $1A,$4B,$FF
+
+.facingRightWarpTiles
+ db $0F,$4E,$FF
+
+.ssAnne5
+ ld a, [wTileInFrontOfPlayer]
+ cp $15
+ jr nz, .notSSAnne5Warp
+ scf
+ jr .done
+.notSSAnne5Warp
+ and a
+ jr .done
+
+IsPlayerStandingOnDoorTileOrWarpTile: ; c49d (3:449d)
+ push hl
+ push de
+ push bc
+ callba IsPlayerStandingOnDoorTile
+ jr c, .done
+ ld a, [W_CURMAPTILESET]
+ add a
+ ld c, a
+ ld b, $0
+ ld hl, WarpTileIDPointers
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, $1
+ aCoord 8, 9
+ call IsInArray
+ jr nc, .done
+ ld hl, wd736
+ res 2, [hl]
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+INCLUDE "data/warp_tile_ids.asm"
+
+PrintSafariZoneSteps: ; c52f (3:452f)
+ ld a, [W_CURMAP] ; W_CURMAP
+ cp SAFARI_ZONE_EAST
+ ret c
+ cp UNKNOWN_DUNGEON_2
+ ret nc
+ ld hl, wTileMap
+ ld b, $3
+ ld c, $7
+ call TextBoxBorder
+ hlCoord 1, 1
+ ld de, wSafariSteps ; wd70d
+ ld bc, $203
+ call PrintNumber
+ hlCoord 4, 1
+ ld de, SafariSteps ; $4579
+ call PlaceString
+ hlCoord 1, 3
+ ld de, SafariBallText
+ call PlaceString
+ ld a, [W_NUMSAFARIBALLS] ; W_NUMSAFARIBALLS
+ cp $a
+ jr nc, .asm_c56d
+ hlCoord 5, 3
+ ld a, $7f
+ ld [hl], a
+.asm_c56d
+ hlCoord 6, 3
+ ld de, W_NUMSAFARIBALLS ; W_NUMSAFARIBALLS
+ ld bc, $102
+ jp PrintNumber
+
+SafariSteps: ; c579 (3:4579)
+ db "/500@"
+
+SafariBallText: ; c57e (3:457e)
+ db "BALL×× @"
+
+GetTileAndCoordsInFrontOfPlayer: ; c586 (3:4586)
+ call GetPredefRegisters
+
+_GetTileAndCoordsInFrontOfPlayer: ; c589 (3:4589)
+ ld a, [W_YCOORD]
+ ld d, a
+ ld a, [W_XCOORD]
+ ld e, a
+ ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
+ and a
+ jr nz, .notFacingDown
+; facing down
+ aCoord 8, 11
+ inc d
+ jr .storeTile
+.notFacingDown
+ cp SPRITE_FACING_UP
+ jr nz, .notFacingUp
+; facing up
+ aCoord 8, 7
+ dec d
+ jr .storeTile
+.notFacingUp
+ cp SPRITE_FACING_LEFT
+ jr nz, .notFacingLeft
+; facing left
+ aCoord 6, 9
+ dec e
+ jr .storeTile
+.notFacingLeft
+ cp SPRITE_FACING_RIGHT
+ jr nz, .storeTile
+; facing right
+ aCoord 10, 9
+ inc e
+.storeTile
+ ld c, a
+ ld [wTileInFrontOfPlayer], a
+ ret
+
+GetTileTwoStepsInFrontOfPlayer: ; c5be (3:45be)
+ xor a
+ ld [$ffdb], a
+ ld hl, W_YCOORD
+ ld a, [hli]
+ ld d, a
+ ld e, [hl]
+ ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
+ and a
+ jr nz, .notFacingDown
+; facing down
+ ld hl, $ffdb
+ set 0, [hl]
+ aCoord 8, 13
+ inc d
+ jr .storeTile
+.notFacingDown
+ cp SPRITE_FACING_UP
+ jr nz, .notFacingUp
+; facing up
+ ld hl, $ffdb
+ set 1, [hl]
+ aCoord 8, 5
+ dec d
+ jr .storeTile
+.notFacingUp
+ cp SPRITE_FACING_LEFT
+ jr nz, .notFacingLeft
+; facing left
+ ld hl, $ffdb
+ set 2, [hl]
+ aCoord 4, 9
+ dec e
+ jr .storeTile
+.notFacingLeft
+ cp SPRITE_FACING_RIGHT
+ jr nz, .storeTile
+; facing right
+ ld hl, $ffdb
+ set 3, [hl]
+ aCoord 12, 9
+ inc e
+.storeTile
+ ld c, a
+ ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a
+ ld [wTileInFrontOfPlayer], a
+ ret
+
+CheckForCollisionWhenPushingBoulder: ; c60b (3:460b)
+ call GetTileTwoStepsInFrontOfPlayer
+ ld hl, W_TILESETCOLLISIONPTR
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+.loop
+ ld a, [hli]
+ cp $ff
+ jr z, .done ; if the tile two steps ahead is not passable
+ cp c
+ jr nz, .loop
+ ld hl, TilePairCollisionsLand
+ call CheckForTilePairCollisions2
+ ld a, $ff
+ jr c, .done ; if there is an elevation difference between the current tile and the one two steps ahead
+ ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult]
+ cp $15 ; stairs tile
+ ld a, $ff
+ jr z, .done ; if the tile two steps ahead is stairs
+ call CheckForBoulderCollisionWithSprites
+.done
+ ld [wTileInFrontOfBoulderAndBoulderCollisionResult], a
+ ret
+
+; sets a to $ff if there is a collision and $00 if there is no collision
+CheckForBoulderCollisionWithSprites: ; c636 (3:4636)
+ ld a, [wBoulderSpriteIndex]
+ dec a
+ swap a
+ ld d, 0
+ ld e, a
+ ld hl, wSpriteStateData2 + $14
+ add hl, de
+ ld a, [hli] ; map Y position
+ ld [$ffdc], a
+ ld a, [hl] ; map X position
+ ld [$ffdd], a
+ ld a, [W_NUMSPRITES]
+ ld c, a
+ ld de, $f
+ ld hl, wSpriteStateData2 + $14
+ ld a, [$ffdb]
+ and $3 ; facing up or down?
+ jr z, .pushingHorizontallyLoop
+.pushingVerticallyLoop
+ inc hl
+ ld a, [$ffdd]
+ cp [hl]
+ jr nz, .nextSprite1 ; if X coordinates don't match
+ dec hl
+ ld a, [hli]
+ ld b, a
+ ld a, [$ffdb]
+ rrca
+ jr c, .pushingDown
+; pushing up
+ ld a, [$ffdc]
+ dec a
+ jr .compareYCoords
+.pushingDown
+ ld a, [$ffdc]
+ inc a
+.compareYCoords
+ cp b
+ jr z, .failure
+.nextSprite1
+ dec c
+ jr z, .success
+ add hl, de
+ jr .pushingVerticallyLoop
+.pushingHorizontallyLoop
+ ld a, [hli]
+ ld b, a
+ ld a, [$ffdc]
+ cp b
+ jr nz, .nextSprite2
+ ld b, [hl]
+ ld a, [$ffdb]
+ bit 2, a
+ jr nz, .pushingLeft
+; pushing right
+ ld a, [$ffdd]
+ inc a
+ jr .compareXCoords
+.pushingLeft
+ ld a, [$ffdd]
+ dec a
+.compareXCoords
+ cp b
+ jr z, .failure
+.nextSprite2
+ dec c
+ jr z, .success
+ add hl, de
+ jr .pushingHorizontallyLoop
+.failure
+ ld a, $ff
+ ret
+.success
+ xor a
+ ret
+
+ApplyOutOfBattlePoisonDamage: ; c69c (3:469c)
+ ld a, [wd730]
+ add a
+ jp c, .noBlackOut ; no black out if joypad states are being simulated
+ ld a, [wPartyCount]
+ and a
+ jp z, .noBlackOut
+ call IncrementDayCareMonExp
+ ld a, [wStepCounter]
+ and $3 ; is the counter a multiple of 4?
+ jp nz, .noBlackOut ; only apply poison damage every fourth step
+ ld [wWhichPokemon], a
+ ld hl, wPartyMon1Status
+ ld de, wPartySpecies
+.applyDamageLoop
+ ld a, [hl]
+ and (1 << PSN)
+ jr z, .nextMon2 ; not poisoned
+ dec hl
+ dec hl
+ ld a, [hld]
+ ld b, a
+ ld a, [hli]
+ or b
+ jr z, .nextMon ; already fainted
+; subtract 1 from HP
+ ld a, [hl]
+ dec a
+ ld [hld], a
+ inc a
+ jr nz, .noBorrow
+; borrow 1 from upper byte of HP
+ dec [hl]
+ inc hl
+ jr .nextMon
+.noBorrow
+ ld a, [hli]
+ or [hl]
+ jr nz, .nextMon ; didn't faint from damage
+; the mon fainted from the damage
+ push hl
+ inc hl
+ inc hl
+ ld [hl], a
+ ld a, [de]
+ ld [wd11e], a
+ push de
+ ld a, [wWhichPokemon]
+ ld hl, wPartyMonNicks
+ call GetPartyMonName
+ xor a
+ ld [wJoyIgnore], a
+ call EnableAutoTextBoxDrawing
+ ld a, $d0
+ ld [$ff8c], a
+ call DisplayTextID
+ pop de
+ pop hl
+.nextMon
+ inc hl
+ inc hl
+.nextMon2
+ inc de
+ ld a, [de]
+ inc a
+ jr z, .applyDamageLoopDone
+ ld bc, wPartyMon2 - wPartyMon1
+ add hl, bc
+ push hl
+ ld hl, wWhichPokemon
+ inc [hl]
+ pop hl
+ jr .applyDamageLoop
+.applyDamageLoopDone
+ ld hl, wPartyMon1Status
+ ld a, [wPartyCount]
+ ld d, a
+ ld e, 0
+.countPoisonedLoop
+ ld a, [hl]
+ and (1 << PSN)
+ or e
+ ld e, a
+ ld bc, wPartyMon2 - wPartyMon1
+ add hl, bc
+ dec d
+ jr nz, .countPoisonedLoop
+ ld a, e
+ and a ; are any party members poisoned?
+ jr z, .skipPoisonEffectAndSound
+ ld b, $2
+ predef ChangeBGPalColor0_4Frames ; change BG white to dark grey for 4 frames
+ ld a, (SFX_02_43 - SFX_Headers_02) / 3
+ call PlaySound
+.skipPoisonEffectAndSound
+ predef AnyPartyAlive
+ ld a, d
+ and a
+ jr nz, .noBlackOut
+ call EnableAutoTextBoxDrawing
+ ld a, $d1
+ ld [$ff8c], a
+ call DisplayTextID
+ ld hl, wd72e
+ set 5, [hl]
+ ld a, $ff
+ jr .done
+.noBlackOut
+ xor a
+.done
+ ld [wd12d], a
+ ret
+
+LoadTilesetHeader: ; c754 (3:4754)
+ call GetPredefRegisters
+ push hl
+ ld d, 0
+ ld a, [W_CURMAPTILESET]
+ add a
+ add a
+ ld b, a
+ add a
+ add b ; a = tileset * 12
+ jr nc, .noCarry
+ inc d
+.noCarry
+ ld e, a
+ ld hl, Tilesets
+ add hl, de
+ ld de, W_TILESETBANK
+ ld c, $b
+.copyTilesetHeaderLoop
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .copyTilesetHeaderLoop
+ ld a, [hl]
+ ld [hTilesetType], a
+ xor a
+ ld [$ffd8], a
+ pop hl
+ ld a, [W_CURMAPTILESET]
+ push hl
+ push de
+ ld hl, DungeonTilesets
+ ld de, $1
+ call IsInArray
+ pop de
+ pop hl
+ jr c, .asm_c797
+ ld a, [W_CURMAPTILESET]
+ ld b, a
+ ld a, [$ff8b]
+ cp b
+ jr z, .done
+.asm_c797
+ ld a, [wDestinationWarpID]
+ cp $ff
+ jr z, .done
+ call LoadDestinationWarpPosition
+ ld a, [W_YCOORD]
+ and $1
+ ld [W_YBLOCKCOORD], a
+ ld a, [W_XCOORD]
+ and $1
+ ld [W_XBLOCKCOORD], a
+.done
+ ret
+
+INCLUDE "data/dungeon_tilesets.asm"
+
+INCLUDE "data/tileset_headers.asm"
+
+IncrementDayCareMonExp: ; c8de (3:48de)
+ ld a, [W_DAYCARE_IN_USE]
+ and a
+ ret z
+ ld hl, wDayCareMonExp + 2
+ inc [hl]
+ ret nz
+ dec hl
+ inc [hl]
+ ret nz
+ dec hl
+ inc [hl]
+ ld a, [hl]
+ cp $50
+ ret c
+ ld a, $50
+ ld [hl], a
+ ret
+
+INCLUDE "data/hide_show_data.asm"
+
+PrintStrengthTxt: ; cd99 (3:4d99)
+ ld hl, wd728
+ set 0, [hl]
+ ld hl, UsedStrengthText
+ call PrintText
+ ld hl, CanMoveBouldersText
+ jp PrintText
+
+UsedStrengthText: ; cdaa (3:4daa)
+ TX_FAR _UsedStrengthText
+ db $08 ; asm
+ ld a, [wcf91]
+ call PlayCry
+ call Delay3
+ jp TextScriptEnd
+
+CanMoveBouldersText: ; cdbb (3:4dbb)
+ TX_FAR _CanMoveBouldersText
+ db "@"
+
+CheckForForcedBikeSurf: ; cdc0 (3:4dc0)
+ ld hl, wd728
+ set 1, [hl]
+ ld a, [wd732]
+ bit 5, a
+ jr nz, .asm_cdec
+ ld a, [W_CURMAP] ; W_CURMAP
+ cp SEAFOAM_ISLANDS_5
+ ret nz
+ ld a, [wd881]
+ and $3
+ cp $3
+ ret z
+ ld hl, CoordsData_cdf7 ; $4df7
+ call ArePlayerCoordsInArray
+ ret nc
+ ld hl, wd728
+ res 1, [hl]
+ ld hl, CurrentTooFastText
+ jp PrintText
+.asm_cdec
+ ld hl, wd728
+ res 1, [hl]
+ ld hl, CyclingIsFunText
+ jp PrintText
+
+CoordsData_cdf7: ; cdf7 (3:4df7)
+ db $0B,$07,$FF
+
+CurrentTooFastText: ; cdfa (3:4dfa)
+ TX_FAR _CurrentTooFastText
+ db "@"
+
+CyclingIsFunText: ; cdff (3:4dff)
+ TX_FAR _CyclingIsFunText
+ db "@"
+
+; function to add an item (in varying quantities) to the player's bag or PC box
+; INPUT:
+; hl = address of inventory (either wNumBagItems or wNumBoxItems)
+; [wcf91] = item ID
+; [wcf96] = item quantity
+; sets carry flag if successful, unsets carry flag if unsuccessful
+AddItemToInventory_: ; ce04 (3:4e04)
+ ld a,[wcf96] ; a = item quantity
+ push af
+ push bc
+ push de
+ push hl
+ push hl
+ ld d,50 ; PC box can hold 50 items
+ ld a,wNumBagItems & $FF
+ cp l
+ jr nz,.checkIfInventoryFull
+ ld a,wNumBagItems >> 8
+ cp h
+ jr nz,.checkIfInventoryFull
+; if the destination is the bag
+ ld d,20 ; bag can hold 20 items
+.checkIfInventoryFull
+ ld a,[hl]
+ sub d
+ ld d,a
+ ld a,[hli]
+ and a
+ jr z,.addNewItem
+.loop
+ ld a,[hli]
+ ld b,a ; b = ID of current item in table
+ ld a,[wcf91] ; a = ID of item being added
+ cp b ; does the current item in the table match the item being added?
+ jp z,.increaseItemQuantity ; if so, increase the item's quantity
+ inc hl
+ ld a,[hl]
+ cp a,$ff ; is it the end of the table?
+ jr nz,.loop
+.addNewItem ; add an item not yet in the inventory
+ pop hl
+ ld a,d
+ and a ; is there room for a new item slot?
+ jr z,.done
+; if there is room
+ inc [hl] ; increment the number of items in the inventory
+ ld a,[hl] ; the number of items will be the index of the new item
+ add a
+ dec a
+ ld c,a
+ ld b,0
+ add hl,bc ; hl = address to store the item
+ ld a,[wcf91]
+ ld [hli],a ; store item ID
+ ld a,[wcf96]
+ ld [hli],a ; store item quantity
+ ld [hl],$ff ; store terminator
+ jp .success
+.increaseItemQuantity ; increase the quantity of an item already in the inventory
+ ld a,[wcf96]
+ ld b,a ; b = quantity to add
+ ld a,[hl] ; a = existing item quantity
+ add b ; a = new item quantity
+ cp a,100
+ jp c,.storeNewQuantity ; if the new quantity is less than 100, store it
+; if the new quantity is greater than or equal to 100,
+; try to max out the current slot and add the rest in a new slot
+ sub a,99
+ ld [wcf96],a ; a = amount left over (to put in the new slot)
+ ld a,d
+ and a ; is there room for a new item slot?
+ jr z,.increaseItemQuantityFailed
+; if so, store 99 in the current slot and store the rest in a new slot
+ ld a,99
+ ld [hli],a
+ jp .loop
+.increaseItemQuantityFailed
+ pop hl
+ and a
+ jr .done
+.storeNewQuantity
+ ld [hl],a
+ pop hl
+.success
+ scf
+.done
+ pop hl
+ pop de
+ pop bc
+ pop bc
+ ld a,b
+ ld [wcf96],a ; restore the initial value from when the function was called
+ ret
+
+; function to remove an item (in varying quantities) from the player's bag or PC box
+; INPUT:
+; hl = address of inventory (either wNumBagItems or wNumBoxItems)
+; [wWhichPokemon] = index (within the inventory) of the item to remove
+; [wcf96] = quantity to remove
+RemoveItemFromInventory_: ; ce74 (3:4e74)
+ push hl
+ inc hl
+ ld a,[wWhichPokemon] ; index (within the inventory) of the item being removed
+ sla a
+ add l
+ ld l,a
+ jr nc,.noCarry
+ inc h
+.noCarry
+ inc hl
+ ld a,[wcf96] ; quantity being removed
+ ld e,a
+ ld a,[hl] ; a = current quantity
+ sub e
+ ld [hld],a ; store new quantity
+ ld [wcf97],a
+ and a
+ jr nz,.skipMovingUpSlots
+; if the remaining quantity is 0,
+; remove the emptied item slot and move up all the following item slots
+.moveSlotsUp
+ ld e,l
+ ld d,h
+ inc de
+ inc de ; de = address of the slot following the emptied one
+.loop ; loop to move up the following slots
+ ld a,[de]
+ inc de
+ ld [hli],a
+ cp a,$ff
+ jr nz,.loop
+; update menu info
+ xor a
+ ld [wListScrollOffset],a
+ ld [wCurrentMenuItem],a
+ ld [wcc2c],a
+ ld [wd07e],a
+ pop hl
+ ld a,[hl] ; a = number of items in inventory
+ dec a ; decrement the number of items
+ ld [hl],a ; store new number of items
+ ld [wd12a],a
+ cp a,2
+ jr c,.done
+ ld [wMaxMenuItem],a
+ jr .done
+.skipMovingUpSlots
+ pop hl
+.done
+ ret
+
+; wild pokemon data: from 4EB8 to 55C7
+
+LoadWildData: ; ceb8 (3:4eb8)
+ ld hl,WildDataPointers
+ ld a,[W_CURMAP]
+
+ ; get wild data for current map
+ ld c,a
+ ld b,0
+ add hl,bc
+ add hl,bc
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a ; hl now points to wild data for current map
+ ld a,[hli]
+ ld [W_GRASSRATE],a
+ and a
+ jr z,.NoGrassData ; if no grass data, skip to surfing data
+ push hl
+ ld de,W_GRASSMONS ; otherwise, load grass data
+ ld bc,$0014
+ call CopyData
+ pop hl
+ ld bc,$0014
+ add hl,bc
+.NoGrassData
+ ld a,[hli]
+ ld [W_WATERRATE],a
+ and a
+ ret z ; if no water data, we're done
+ ld de,W_WATERMONS ; otherwise, load surfing data
+ ld bc,$0014
+ jp CopyData
+
+INCLUDE "data/wild_mons.asm"
+
+INCLUDE "engine/items/items.asm"
+
+DrawBadges: ; ea03 (3:6a03)
+; Draw 4x2 gym leader faces, with the faces replaced by
+; badges if they are owned. Used in the player status screen.
+
+; In Japanese versions, names are displayed above faces.
+; Instead of removing relevant code, the name graphics were erased.
+
+; Tile ids for face/badge graphics.
+ ld de, wTrainerFacingDirection
+ ld hl, .FaceBadgeTiles
+ ld bc, 8
+ call CopyData
+
+; Booleans for each badge.
+ ld hl, wcd49
+ ld bc, 8
+ xor a
+ call FillMemory
+
+; Alter these based on owned badges.
+ ld de, wcd49
+ ld hl, wTrainerFacingDirection
+ ld a, [W_OBTAINEDBADGES]
+ ld b, a
+ ld c, 8
+.CheckBadge
+ srl b
+ jr nc, .NextBadge
+ ld a, [hl]
+ add 4 ; Badge graphics are after each face
+ ld [hl], a
+ ld a, 1
+ ld [de], a
+.NextBadge
+ inc hl
+ inc de
+ dec c
+ jr nz, .CheckBadge
+
+; Draw two rows of badges.
+ ld hl, wWhichTrade
+ ld a, $d8 ; [1]
+ ld [hli], a
+ ld [hl], $60 ; First name
+
+ hlCoord 2, 11
+ ld de, wcd49
+ call .DrawBadgeRow
+
+ hlCoord 2, 14
+ ld de, wcd49 + 4
+; call .DrawBadgeRow
+; ret
+
+.DrawBadgeRow ; ea4c (3:6a4c)
+; Draw 4 badges.
+
+ ld c, 4
+.DrawBadge
+ push de
+ push hl
+
+; Badge no.
+ ld a, [wWhichTrade]
+ ld [hli], a
+ inc a
+ ld [wWhichTrade], a
+
+; Names aren't printed if the badge is owned.
+ ld a, [de]
+ and a
+ ld a, [wTrainerEngageDistance]
+ jr nz, .SkipName
+ call .PlaceTiles
+ jr .PlaceBadge
+
+.SkipName
+ inc a
+ inc a
+ inc hl
+
+.PlaceBadge
+ ld [wTrainerEngageDistance], a
+ ld de, 20 - 1
+ add hl, de
+ ld a, [wTrainerFacingDirection]
+ call .PlaceTiles
+ add hl, de
+ call .PlaceTiles
+
+; Shift badge array back one byte.
+ push bc
+ ld hl, wTrainerFacingDirection + 1
+ ld de, wTrainerFacingDirection
+ ld bc, 8
+ call CopyData
+ pop bc
+
+ pop hl
+ ld de, 4
+ add hl, de
+
+ pop de
+ inc de
+ dec c
+ jr nz, .DrawBadge
+ ret
+
+.PlaceTiles
+ ld [hli], a
+ inc a
+ ld [hl], a
+ inc a
+ ret
+
+.FaceBadgeTiles
+ db $20, $28, $30, $38, $40, $48, $50, $58
+
+GymLeaderFaceAndBadgeTileGraphics: ; ea9e (3:6a9e)
+ INCBIN "gfx/badges.2bpp"
+
+; replaces a tile block with the one specified in [wNewTileBlockID]
+; and redraws the map view if necessary
+; b = Y
+; c = X
+ReplaceTileBlock: ; ee9e (3:6e9e)
+ call GetPredefRegisters
+ ld hl, wOverworldMap
+ ld a, [W_CURMAPWIDTH]
+ add $6
+ ld e, a
+ ld d, $0
+ add hl, de
+ add hl, de
+ add hl, de
+ ld e, $3
+ add hl, de
+ ld e, a
+ ld a, b
+ and a
+ jr z, .addX
+; add width * Y
+.addWidthYTimesLoop
+ add hl, de
+ dec b
+ jr nz, .addWidthYTimesLoop
+.addX
+ add hl, bc ; add X
+ ld a, [wNewTileBlockID]
+ ld [hl], a
+ ld a, [wCurrentTileBlockMapViewPointer]
+ ld c, a
+ ld a, [wCurrentTileBlockMapViewPointer + 1]
+ ld b, a
+ call CompareHLWithBC
+ ret c ; return if the replaced tile block is below the map view in memory
+ push hl
+ ld l, e
+ ld h, $0
+ ld e, $6
+ ld d, h
+ add hl, hl
+ add hl, hl
+ add hl, de
+ add hl, bc
+ pop bc
+ call CompareHLWithBC
+ ret c ; return if the replaced tile block is above the map view in memory
+
+RedrawMapView: ; eedc (3:6edc)
+ ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+ inc a
+ ret z
+ ld a, [H_AUTOBGTRANSFERENABLED]
+ push af
+ ld a, [hTilesetType]
+ push af
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ld [hTilesetType], a ; no flower/water BG tile animations
+ call LoadCurrentMapView
+ call GoPAL_SET_CF1C
+ ld hl, wMapViewVRAMPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, -2 * 32
+ add hl, de
+ ld a, h
+ and $3
+ or $98
+ ld a, l
+ ld [wHPBarMaxHP], a
+ ld a, h
+ ld [wHPBarMaxHP + 1], a
+ ld a, 2
+ ld [$ffbe], a
+ ld c, 9 ; number of rows of 2x2 tiles (this covers the whole screen)
+.redrawRowLoop
+ push bc
+ push hl
+ push hl
+ ld hl, wTileMap - 2 * 20
+ ld de, 20
+ ld a, [$ffbe]
+.asm_ef1a
+ add hl, de
+ dec a
+ jr nz, .asm_ef1a
+ call CopyToScreenEdgeTiles
+ pop hl
+ ld de, $20
+ ld a, [$ffbe]
+ ld c, a
+.asm_ef28
+ add hl, de
+ ld a, h
+ and $3
+ or $98
+ dec c
+ jr nz, .asm_ef28
+ ld [H_SCREENEDGEREDRAWADDR + 1], a
+ ld a, l
+ ld [H_SCREENEDGEREDRAWADDR], a
+ ld a, REDRAWROW
+ ld [H_SCREENEDGEREDRAW], a
+ call DelayFrame
+ ld hl, $ffbe
+ inc [hl]
+ inc [hl]
+ pop hl
+ pop bc
+ dec c
+ jr nz, .redrawRowLoop
+ pop af
+ ld [hTilesetType], a
+ pop af
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ret
+
+CompareHLWithBC: ; ef4e (3:6f4e)
+ ld a, h
+ sub b
+ ret nz
+ ld a, l
+ sub c
+ ret
+
+INCLUDE "engine/overworld/cut.asm"
+
+MarkTownVisitedAndLoadMissableObjects: ; f113 (3:7113)
+ ld a, [W_CURMAP]
+ cp ROUTE_1
+ jr nc, .notInTown
+ ld c, a
+ ld b, $1
+ ld hl, W_TOWNVISITEDFLAG ; mark town as visited (for flying)
+ predef FlagActionPredef
+.notInTown
+ ld hl, MapHSPointers
+ ld a, [W_CURMAP]
+ ld b, $0
+ ld c, a
+ add hl, bc
+ add hl, bc
+ ld a, [hli] ; load missable objects pointer in hl
+ ld h, [hl]
+ ; fall through
+
+LoadMissableObjects: ; f132 (3:7132)
+ ld l, a
+ push hl
+ ld de, MapHS00 ; calculate difference between out pointer and the base pointer
+ ld a, l
+ sub e
+ jr nc, .asm_f13c
+ dec h
+.asm_f13c
+ ld l, a
+ ld a, h
+ sub d
+ ld h, a
+ ld a, h
+ ld [H_DIVIDEND], a
+ ld a, l
+ ld [H_DIVIDEND+1], a
+ xor a
+ ld [H_DIVIDEND+2], a
+ ld [H_DIVIDEND+3], a
+ ld a, $3
+ ld [H_DIVISOR], a
+ ld b, $2
+ call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours)
+ ld a, [W_CURMAP] ; W_CURMAP
+ ld b, a
+ ld a, [H_DIVIDEND+3]
+ ld c, a ; store global offset in c
+ ld de, W_MISSABLEOBJECTLIST
+ pop hl
+.writeMissableObjectsListLoop
+ ld a, [hli]
+ cp $ff
+ jr z, .done ; end of list
+ cp b
+ jr nz, .done ; not for current map anymore
+ ld a, [hli]
+ inc hl
+ ld [de], a ; write (map-local) sprite ID
+ inc de
+ ld a, c
+ inc c
+ ld [de], a ; write (global) missable object index
+ inc de
+ jr .writeMissableObjectsListLoop
+.done
+ ld a, $ff
+ ld [de], a ; write sentinel
+ ret
+
+InitializeMissableObjectsFlags: ; f175 (3:7175)
+ ld hl, W_MISSABLEOBJECTFLAGS
+ ld bc, $20
+ xor a
+ call FillMemory ; clear missable objects flags
+ ld hl, MapHS00
+ xor a
+ ld [wd048], a
+.missableObjectsLoop
+ ld a, [hli]
+ cp $ff ; end of list
+ ret z
+ push hl
+ inc hl
+ ld a, [hl]
+ cp Hide
+ jr nz, .asm_f19d
+ ld hl, W_MISSABLEOBJECTFLAGS
+ ld a, [wd048]
+ ld c, a
+ ld b, $1
+ call MissableObjectFlagAction ; set flag iff Item is hidden
+.asm_f19d
+ ld hl, wd048
+ inc [hl]
+ pop hl
+ inc hl
+ inc hl
+ jr .missableObjectsLoop
+
+; tests if current sprite is a missable object that is hidden/has been removed
+IsObjectHidden: ; f1a6 (3:71a6)
+ ld a, [H_CURRENTSPRITEOFFSET]
+ swap a
+ ld b, a
+ ld hl, W_MISSABLEOBJECTLIST
+.loop
+ ld a, [hli]
+ cp $ff
+ jr z, .notHidden ; not missable -> not hidden
+ cp b
+ ld a, [hli]
+ jr nz, .loop
+ ld c, a
+ ld b, $2
+ ld hl, W_MISSABLEOBJECTFLAGS
+ call MissableObjectFlagAction
+ ld a, c
+ and a
+ jr nz, .hidden
+.notHidden
+ xor a
+.hidden
+ ld [$ffe5], a
+ ret
+
+; adds missable object (items, leg. pokemon, etc.) to the map
+; [wcc4d]: index of the missable object to be added (global index)
+ShowObject: ; f1c8 (3:71c8)
+ShowObject2:
+ ld hl, W_MISSABLEOBJECTFLAGS
+ ld a, [wcc4d]
+ ld c, a
+ ld b, $0
+ call MissableObjectFlagAction ; reset "removed" flag
+ jp UpdateSprites
+
+; removes missable object (items, leg. pokemon, etc.) from the map
+; [wcc4d]: index of the missable object to be removed (global index)
+HideObject: ; f1d7 (3:71d7)
+ ld hl, W_MISSABLEOBJECTFLAGS
+ ld a, [wcc4d]
+ ld c, a
+ ld b, $1
+ call MissableObjectFlagAction ; set "removed" flag
+ jp UpdateSprites
+
+MissableObjectFlagAction:
+; identical to FlagAction
+
+ push hl
+ push de
+ push bc
+
+ ; bit
+ ld a, c
+ ld d, a
+ and 7
+ ld e, a
+
+ ; byte
+ ld a, d
+ srl a
+ srl a
+ srl a
+ add l
+ ld l, a
+ jr nc, .ok
+ inc h
+.ok
+
+ ; d = 1 << e (bitmask)
+ inc e
+ ld d, 1
+.shift
+ dec e
+ jr z, .shifted
+ sla d
+ jr .shift
+.shifted
+
+ ld a, b
+ and a
+ jr z, .reset
+ cp 2
+ jr z, .read
+
+.set
+ ld a, [hl]
+ ld b, a
+ ld a, d
+ or b
+ ld [hl], a
+ jr .done
+
+.reset
+ ld a, [hl]
+ ld b, a
+ ld a, d
+ xor $ff
+ and b
+ ld [hl], a
+ jr .done
+
+.read
+ ld a, [hl]
+ ld b, a
+ ld a, d
+ and b
+
+.done
+ pop bc
+ pop de
+ pop hl
+ ld c, a
+ ret
+
+TryPushingBoulder: ; f225 (3:7225)
+ ld a, [wd728]
+ bit 0, a ; using Strength?
+ ret z
+ ld a, [wFlags_0xcd60]
+ bit 1, a ; has boulder dust animation from previous push played yet?
+ ret nz
+ xor a
+ ld [$ff8c], a
+ call IsSpriteInFrontOfPlayer
+ ld a, [$ff8c]
+ ld [wBoulderSpriteIndex], a
+ and a
+ jp z, ResetBoulderPushFlags
+ ld hl, wSpriteStateData1 + 1
+ ld d, $0
+ ld a, [$ff8c]
+ swap a
+ ld e, a
+ add hl, de
+ res 7, [hl]
+ call GetSpriteMovementByte2Pointer
+ ld a, [hl]
+ cp BOULDER_MOVEMENT_BYTE_2
+ jp nz, ResetBoulderPushFlags
+ ld hl, wFlags_0xcd60
+ bit 6, [hl]
+ set 6, [hl] ; indicate that the player has tried pushing
+ ret z ; the player must try pushing twice before the boulder will move
+ ld a, [hJoyHeld]
+ and $f0
+ ret z
+ predef CheckForCollisionWhenPushingBoulder
+ ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult]
+ and a ; was there a collision?
+ jp nz, ResetBoulderPushFlags
+ ld a, [hJoyHeld]
+ ld b, a
+ ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
+ cp SPRITE_FACING_UP
+ jr z, .pushBoulderUp
+ cp SPRITE_FACING_LEFT
+ jr z, .pushBoulderLeft
+ cp SPRITE_FACING_RIGHT
+ jr z, .pushBoulderRight
+.pushBoulderDown
+ bit 7, b
+ ret z
+ ld de, PushBoulderDownMovementData
+ jr .done
+.pushBoulderUp
+ bit 6, b
+ ret z
+ ld de, PushBoulderUpMovementData
+ jr .done
+.pushBoulderLeft
+ bit 5, b
+ ret z
+ ld de, PushBoulderLeftMovementData
+ jr .done
+.pushBoulderRight
+ bit 4, b
+ ret z
+ ld de, PushBoulderRightMovementData
+.done
+ call MoveSprite
+ ld a, (SFX_02_53 - SFX_Headers_02) / 3
+ call PlaySound
+ ld hl, wFlags_0xcd60
+ set 1, [hl]
+ ret
+
+PushBoulderUpMovementData: ; f2ad (3:72ad)
+ db NPC_MOVEMENT_UP,$FF
+
+PushBoulderDownMovementData: ; f2af (3:72af)
+ db NPC_MOVEMENT_DOWN,$FF
+
+PushBoulderLeftMovementData: ; f2b1 (3:72b1)
+ db NPC_MOVEMENT_LEFT,$FF
+
+PushBoulderRightMovementData: ; f2b3 (3:72b3)
+ db NPC_MOVEMENT_RIGHT,$FF
+
+DoBoulderDustAnimation: ; f2b5 (3:72b5)
+ ld a, [wd730]
+ bit 0, a
+ ret nz
+ callab AnimateBoulderDust
+ call DiscardButtonPresses
+ ld [wJoyIgnore], a
+ call ResetBoulderPushFlags
+ set 7, [hl]
+ ld a, [wBoulderSpriteIndex]
+ ld [H_SPRITEINDEX], a
+ call GetSpriteMovementByte2Pointer
+ ld [hl], $10
+ ld a, (SFX_02_56 - SFX_Headers_02) / 3
+ jp PlaySound
+
+ResetBoulderPushFlags: ; f2dd (3:72dd)
+ ld hl, wFlags_0xcd60
+ res 1, [hl]
+ res 6, [hl]
+ ret
+
+_AddPartyMon: ; f2e5 (3:72e5)
+ ld de, wPartyCount ; wPartyCount
+ ld a, [wcc49]
+ and $f
+ jr z, .asm_f2f2
+ ld de, wEnemyPartyCount ; wEnemyPartyCount
+.asm_f2f2
+ ld a, [de]
+ inc a
+ cp PARTY_LENGTH + 1
+ ret nc
+ ld [de], a
+ ld a, [de]
+ ld [$ffe4], a
+ add e
+ ld e, a
+ jr nc, .asm_f300
+ inc d
+.asm_f300
+ ld a, [wcf91]
+ ld [de], a
+ inc de
+ ld a, $ff
+ ld [de], a
+ ld hl, wPartyMonOT ; wd273
+ ld a, [wcc49]
+ and $f
+ jr z, .asm_f315
+ ld hl, wEnemyMonOT
+.asm_f315
+ ld a, [$ffe4]
+ dec a
+ call SkipFixedLengthTextEntries
+ ld d, h
+ ld e, l
+ ld hl, wPlayerName ; wd158
+ ld bc, $b
+ call CopyData
+ ld a, [wcc49]
+ and a
+ jr nz, .asm_f33f
+ ld hl, wPartyMonNicks ; wPartyMonNicks
+ ld a, [$ffe4]
+ dec a
+ call SkipFixedLengthTextEntries
+ ld a, $2
+ ld [wd07d], a
+ predef AskName
+.asm_f33f
+ ld hl, wPartyMons
+ ld a, [wcc49]
+ and $f
+ jr z, .asm_f34c
+ ld hl, wEnemyMons
+.asm_f34c
+ ld a, [$ffe4]
+ dec a
+ ld bc, wPartyMon2 - wPartyMon1
+ call AddNTimes
+ ld e, l
+ ld d, h
+ push hl
+ ld a, [wcf91]
+ ld [wd0b5], a
+ call GetMonHeader
+ ld hl, W_MONHEADER
+ ld a, [hli]
+ ld [de], a
+ inc de
+ pop hl
+ push hl
+ ld a, [wcc49]
+ and $f
+ ld a, $98 ; set enemy trainer mon IVs to fixed average values
+ ld b, $88
+ jr nz, .writeFreshMonData
+ ld a, [wcf91]
+ ld [wd11e], a
+ push de
+ predef IndexToPokedex
+ pop de
+ ld a, [wd11e]
+ dec a
+ ld c, a
+ ld b, $2
+ ld hl, wPokedexOwned ; wPokedexOwned
+ call FlagAction
+ ld a, c
+ ld [wd153], a
+ ld a, [wd11e]
+ dec a
+ ld c, a
+ ld b, $1
+ push bc
+ call FlagAction
+ pop bc
+ ld hl, wPokedexSeen ; wd30a
+ call FlagAction
+ pop hl
+ push hl
+ ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+ and a
+ jr nz, .copyEnemyMonData
+ call Random ; generate random IVs
+ ld b, a
+ call Random
+.writeFreshMonData ; f3b3
+ push bc
+ ld bc, $1b
+ add hl, bc
+ pop bc
+ ld [hli], a
+ ld [hl], b ; write IVs
+ ld bc, $fff4
+ add hl, bc
+ ld a, $1
+ ld c, a
+ xor a
+ ld b, a
+ call CalcStat ; calc HP stat (set cur Hp to max HP)
+ ld a, [H_MULTIPLICAND+1]
+ ld [de], a
+ inc de
+ ld a, [H_MULTIPLICAND+2]
+ ld [de], a
+ inc de
+ xor a
+ ld [de], a ; level (?)
+ inc de
+ ld [de], a ; status ailments
+ inc de
+ jr .copyMonTypesAndMoves
+.copyEnemyMonData
+ ld bc, $1b
+ add hl, bc
+ ld a, [wEnemyMonDVs] ; copy IVs from cur enemy mon
+ ld [hli], a
+ ld a, [wEnemyMonDVs + 1]
+ ld [hl], a
+ ld a, [wEnemyMonHP] ; copy HP from cur enemy mon
+ ld [de], a
+ inc de
+ ld a, [wEnemyMonHP+1]
+ ld [de], a
+ inc de
+ xor a
+ ld [de], a ; level (?)
+ inc de
+ ld a, [wEnemyMonStatus] ; copy status ailments from cur enemy mon
+ ld [de], a
+ inc de
+.copyMonTypesAndMoves
+ ld hl, W_MONHTYPES
+ ld a, [hli] ; type 1
+ ld [de], a
+ inc de
+ ld a, [hli] ; type 2
+ ld [de], a
+ inc de
+ ld a, [hli] ; unused (?)
+ ld [de], a
+ ld hl, W_MONHMOVES
+ ld a, [hli]
+ inc de
+ push de
+ ld [de], a
+ ld a, [hli]
+ inc de
+ ld [de], a
+ ld a, [hli]
+ inc de
+ ld [de], a
+ ld a, [hli]
+ inc de
+ ld [de], a
+ push de
+ dec de
+ dec de
+ dec de
+ xor a
+ ld [wHPBarMaxHP], a
+ predef WriteMonMoves
+ pop de
+ ld a, [wPlayerID] ; set trainer ID to player ID
+ inc de
+ ld [de], a
+ ld a, [wPlayerID + 1]
+ inc de
+ ld [de], a
+ push de
+ ld a, [W_CURENEMYLVL]
+ ld d, a
+ callab CalcExperience
+ pop de
+ inc de
+ ld a, [H_MULTIPLICAND] ; write experience
+ ld [de], a
+ inc de
+ ld a, [H_MULTIPLICAND+1]
+ ld [de], a
+ inc de
+ ld a, [H_MULTIPLICAND+2]
+ ld [de], a
+ xor a
+ ld b, $a
+.writeEVsLoop ; set all EVs to 0
+ inc de
+ ld [de], a
+ dec b
+ jr nz, .writeEVsLoop
+ inc de
+ inc de
+ pop hl
+ call AddPartyMon_WriteMovePP
+ inc de
+ ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL
+ ld [de], a
+ inc de
+ ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+ dec a
+ jr nz, .calcFreshStats
+ ld hl, wEnemyMonMaxHP ; wEnemyMonMaxHP
+ ld bc, $a
+ call CopyData ; copy stats of cur enemy mon
+ pop hl
+ jr .done
+.calcFreshStats
+ pop hl
+ ld bc, $10
+ add hl, bc
+ ld b, $0
+ call CalcStats ; calculate fresh set of stats
+.done
+ scf
+ ret
+
+LoadMovePPs: ; f473 (3:7473)
+ call GetPredefRegisters
+ ; fallthrough
+AddPartyMon_WriteMovePP: ; f476 (3:7476)
+ ld b, $4
+.pploop
+ ld a, [hli] ; read move ID
+ and a
+ jr z, .empty
+ dec a
+ push hl
+ push de
+ push bc
+ ld hl, Moves
+ ld bc, $6
+ call AddNTimes
+ ld de, wcd6d
+ ld a, BANK(Moves)
+ call FarCopyData
+ pop bc
+ pop de
+ pop hl
+ ld a, [wcd72] ; sixth move byte = pp
+.empty
+ inc de
+ ld [de], a
+ dec b
+ jr nz, .pploop ; there are still moves to read
+ ret
+
+; adds enemy mon [wcf91] (at position [wWhichPokemon] in enemy list) to own party
+; used in the cable club trade center
+_AddEnemyMonToPlayerParty: ; f49d (3:749d)
+ ld hl, wPartyCount
+ ld a, [hl]
+ cp PARTY_LENGTH
+ scf
+ ret z ; party full, return failure
+ inc a
+ ld [hl], a ; add 1 to party members
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [wcf91]
+ ld [hli], a ; add mon as last list entry
+ ld [hl], $ff ; write new sentinel
+ ld hl, wPartyMons
+ ld a, [wPartyCount]
+ dec a
+ ld bc, wPartyMon2 - wPartyMon1
+ call AddNTimes
+ ld e, l
+ ld d, h
+ ld hl, wLoadedMon
+ call CopyData ; write new mon's data (from wLoadedMon)
+ ld hl, wPartyMonOT
+ ld a, [wPartyCount]
+ dec a
+ call SkipFixedLengthTextEntries
+ ld d, h
+ ld e, l
+ ld hl, wEnemyMonOT
+ ld a, [wWhichPokemon]
+ call SkipFixedLengthTextEntries
+ ld bc, $000b
+ call CopyData ; write new mon's OT name (from an enemy mon)
+ ld hl, wPartyMonNicks
+ ld a, [wPartyCount]
+ dec a
+ call SkipFixedLengthTextEntries
+ ld d, h
+ ld e, l
+ ld hl, wEnemyMonNicks
+ ld a, [wWhichPokemon]
+ call SkipFixedLengthTextEntries
+ ld bc, $000b
+ call CopyData ; write new mon's nickname (from an enemy mon)
+ ld a, [wcf91]
+ ld [wd11e], a
+ predef IndexToPokedex
+ ld a, [wd11e]
+ dec a
+ ld c, a
+ ld b, $1
+ ld hl, wPokedexOwned
+ push bc
+ call FlagAction ; add to owned pokemon
+ pop bc
+ ld hl, wPokedexSeen
+ call FlagAction ; add to seen pokemon
+ and a
+ ret ; return success
+
+Func_f51e: ; f51e (3:751e)
+ ld a, [wcf95]
+ and a
+ jr z, .checkPartyMonSlots
+ cp $2
+ jr z, .checkPartyMonSlots
+ cp $3
+ ld hl, wDayCareMon
+ jr z, .asm_f575
+ ld hl, W_NUMINBOX ; wda80
+ ld a, [hl]
+ cp MONS_PER_BOX
+ jr nz, .partyOrBoxNotFull
+ jr .boxFull
+.checkPartyMonSlots
+ ld hl, wPartyCount ; wPartyCount
+ ld a, [hl]
+ cp PARTY_LENGTH
+ jr nz, .partyOrBoxNotFull
+.boxFull
+ scf
+ ret
+.partyOrBoxNotFull
+ inc a
+ ld [hl], a ; increment number of mons in party/box
+ ld c, a
+ ld b, $0
+ add hl, bc
+ ld a, [wcf95]
+ cp $2
+ ld a, [wDayCareMon]
+ jr z, .asm_f556
+ ld a, [wcf91]
+.asm_f556
+ ld [hli], a ; write new mon ID
+ ld [hl], $ff ; write new sentinel
+ ld a, [wcf95]
+ dec a
+ ld hl, wPartyMons
+ ld bc, wPartyMon2 - wPartyMon1 ; $2c
+ ld a, [wPartyCount] ; wPartyCount
+ jr nz, .skipToNewMonEntry
+ ld hl, wBoxMons
+ ld bc, wBoxMon2 - wBoxMon1 ; $21
+ ld a, [W_NUMINBOX] ; wda80
+.skipToNewMonEntry
+ dec a
+ call AddNTimes
+.asm_f575
+ push hl
+ ld e, l
+ ld d, h
+ ld a, [wcf95]
+ and a
+ ld hl, wBoxMons
+ ld bc, wBoxMon2 - wBoxMon1 ; $21
+ jr z, .asm_f591
+ cp $2
+ ld hl, wDayCareMon
+ jr z, .asm_f597
+ ld hl, wPartyMons
+ ld bc, wPartyMon2 - wPartyMon1 ; $2c
+.asm_f591
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ call AddNTimes
+.asm_f597
+ push hl
+ push de
+ ld bc, wBoxMon2 - wBoxMon1
+ call CopyData
+ pop de
+ pop hl
+ ld a, [wcf95]
+ and a
+ jr z, .asm_f5b4
+ cp $2
+ jr z, .asm_f5b4
+ ld bc, wBoxMon2 - wBoxMon1
+ add hl, bc
+ ld a, [hl]
+ inc de
+ inc de
+ inc de
+ ld [de], a
+.asm_f5b4
+ ld a, [wcf95]
+ cp $3
+ ld de, W_DAYCAREMONOT
+ jr z, .asm_f5d3
+ dec a
+ ld hl, wPartyMonOT ; wd273
+ ld a, [wPartyCount] ; wPartyCount
+ jr nz, .asm_f5cd
+ ld hl, wBoxMonOT
+ ld a, [W_NUMINBOX] ; wda80
+.asm_f5cd
+ dec a
+ call SkipFixedLengthTextEntries
+ ld d, h
+ ld e, l
+.asm_f5d3
+ ld hl, wBoxMonOT
+ ld a, [wcf95]
+ and a
+ jr z, .asm_f5e6
+ ld hl, W_DAYCAREMONOT
+ cp $2
+ jr z, .asm_f5ec
+ ld hl, wPartyMonOT ; wd273
+.asm_f5e6
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ call SkipFixedLengthTextEntries
+.asm_f5ec
+ ld bc, $b
+ call CopyData
+ ld a, [wcf95]
+ cp $3
+ ld de, W_DAYCAREMONNAME
+ jr z, .asm_f611
+ dec a
+ ld hl, wPartyMonNicks ; wPartyMonNicks
+ ld a, [wPartyCount] ; wPartyCount
+ jr nz, .asm_f60b
+ ld hl, wBoxMonNicks
+ ld a, [W_NUMINBOX] ; wda80
+.asm_f60b
+ dec a
+ call SkipFixedLengthTextEntries
+ ld d, h
+ ld e, l
+.asm_f611
+ ld hl, wBoxMonNicks
+ ld a, [wcf95]
+ and a
+ jr z, .asm_f624
+ ld hl, W_DAYCAREMONNAME
+ cp $2
+ jr z, .asm_f62a
+ ld hl, wPartyMonNicks ; wPartyMonNicks
+.asm_f624
+ ld a, [wWhichPokemon] ; wWhichPokemon
+ call SkipFixedLengthTextEntries
+.asm_f62a
+ ld bc, $b
+ call CopyData
+ pop hl
+ ld a, [wcf95]
+ cp $1
+ jr z, .asm_f664
+ cp $3
+ jr z, .asm_f664
+ push hl
+ srl a
+ add $2
+ ld [wcc49], a
+ call LoadMonData
+ callba CalcLevelFromExperience
+ ld a, d
+ ld [W_CURENEMYLVL], a ; W_CURENEMYLVL
+ pop hl
+ ld bc, wBoxMon2 - wBoxMon1
+ add hl, bc
+ ld [hli], a
+ ld d, h
+ ld e, l
+ ld bc, $ffee
+ add hl, bc
+ ld b, $1
+ call CalcStats
+.asm_f664
+ and a
+ ret
+
+
+FlagActionPredef:
+ call GetPredefRegisters
+
+FlagAction:
+; Perform action b on bit c
+; in the bitfield at hl.
+; 0: reset
+; 1: set
+; 2: read
+; Return the result in c.
+
+ push hl
+ push de
+ push bc
+
+ ; bit
+ ld a, c
+ ld d, a
+ and 7
+ ld e, a
+
+ ; byte
+ ld a, d
+ srl a
+ srl a
+ srl a
+ add l
+ ld l, a
+ jr nc, .ok
+ inc h
+.ok
+
+ ; d = 1 << e (bitmask)
+ inc e
+ ld d, 1
+.shift
+ dec e
+ jr z, .shifted
+ sla d
+ jr .shift
+.shifted
+
+ ld a, b
+ and a
+ jr z, .reset
+ cp 2
+ jr z, .read
+
+.set
+ ld b, [hl]
+ ld a, d
+ or b
+ ld [hl], a
+ jr .done
+
+.reset
+ ld b, [hl]
+ ld a, d
+ xor $ff
+ and b
+ ld [hl], a
+ jr .done
+
+.read
+ ld b, [hl]
+ ld a, d
+ and b
+.done
+ pop bc
+ pop de
+ pop hl
+ ld c, a
+ ret
+
+
+HealParty:
+; Restore HP and PP.
+
+ ld hl, wPartySpecies
+ ld de, wPartyMon1HP
+.healmon
+ ld a, [hli]
+ cp $ff
+ jr z, .done
+
+ push hl
+ push de
+
+ ld hl, wPartyMon1Status - wPartyMon1HP
+ add hl, de
+ xor a
+ ld [hl], a
+
+ push de
+ ld b, NUM_MOVES ; A Pokémon has 4 moves
+.pp
+ ld hl, wPartyMon1Moves - wPartyMon1HP
+ add hl, de
+
+ ld a, [hl]
+ and a
+ jr z, .nextmove
+
+ dec a
+ ld hl, wPartyMon1PP - wPartyMon1HP
+ add hl, de
+
+ push hl
+ push de
+ push bc
+
+ ld hl, Moves
+ ld bc, $0006
+ call AddNTimes
+ ld de, wcd6d
+ ld a, BANK(Moves)
+ call FarCopyData
+ ld a, [wcd72] ; default pp
+
+ pop bc
+ pop de
+ pop hl
+
+ inc de
+ push bc
+ ld b, a
+ ld a, [hl]
+ and $c0
+ add b
+ ld [hl], a
+ pop bc
+
+.nextmove
+ dec b
+ jr nz, .pp
+ pop de
+
+ ld hl, wPartyMon1MaxHP - wPartyMon1HP
+ add hl, de
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+
+ pop de
+ pop hl
+
+ push hl
+ ld bc, wPartyMon2 - wPartyMon1
+ ld h, d
+ ld l, e
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ jr .healmon
+
+.done
+ xor a
+ ld [wWhichPokemon], a
+ ld [wd11e], a
+
+ ld a, [wPartyCount]
+ ld b, a
+.ppup
+ push bc
+ call RestoreBonusPP
+ pop bc
+ ld hl, wWhichPokemon
+ inc [hl]
+ dec b
+ jr nz, .ppup
+ ret
+
+
+DivideBCDPredef::
+DivideBCDPredef2::
+DivideBCDPredef3::
+DivideBCDPredef4::
+ call GetPredefRegisters
+
+DivideBCD::
+ xor a
+ ld [$ffa5], a
+ ld [$ffa6], a
+ ld [$ffa7], a
+ ld d, $1
+.asm_f72a
+ ld a, [$ffa2]
+ and $f0
+ jr nz, .asm_f75b
+ inc d
+ ld a, [$ffa2]
+ swap a
+ and $f0
+ ld b, a
+ ld a, [$ffa3]
+ swap a
+ ld [$ffa3], a
+ and $f
+ or b
+ ld [$ffa2], a
+ ld a, [$ffa3]
+ and $f0
+ ld b, a
+ ld a, [$ffa4]
+ swap a
+ ld [$ffa4], a
+ and $f
+ or b
+ ld [$ffa3], a
+ ld a, [$ffa4]
+ and $f0
+ ld [$ffa4], a
+ jr .asm_f72a
+.asm_f75b
+ push de
+ push de
+ call Func_f800
+ pop de
+ ld a, b
+ swap a
+ and $f0
+ ld [$ffa5], a
+ dec d
+ jr z, .asm_f7bc
+ push de
+ call Func_f7d7
+ call Func_f800
+ pop de
+ ld a, [$ffa5]
+ or b
+ ld [$ffa5], a
+ dec d
+ jr z, .asm_f7bc
+ push de
+ call Func_f7d7
+ call Func_f800
+ pop de
+ ld a, b
+ swap a
+ and $f0
+ ld [$ffa6], a
+ dec d
+ jr z, .asm_f7bc
+ push de
+ call Func_f7d7
+ call Func_f800
+ pop de
+ ld a, [$ffa6]
+ or b
+ ld [$ffa6], a
+ dec d
+ jr z, .asm_f7bc
+ push de
+ call Func_f7d7
+ call Func_f800
+ pop de
+ ld a, b
+ swap a
+ and $f0
+ ld [$ffa7], a
+ dec d
+ jr z, .asm_f7bc
+ push de
+ call Func_f7d7
+ call Func_f800
+ pop de
+ ld a, [$ffa7]
+ or b
+ ld [$ffa7], a
+.asm_f7bc
+ ld a, [$ffa5]
+ ld [$ffa2], a
+ ld a, [$ffa6]
+ ld [$ffa3], a
+ ld a, [$ffa7]
+ ld [$ffa4], a
+ pop de
+ ld a, $6
+ sub d
+ and a
+ ret z
+.asm_f7ce
+ push af
+ call Func_f7d7
+ pop af
+ dec a
+ jr nz, .asm_f7ce
+ ret
+
+Func_f7d7: ; f7d7 (3:77d7)
+ ld a, [$ffa4]
+ swap a
+ and $f
+ ld b, a
+ ld a, [$ffa3]
+ swap a
+ ld [$ffa3], a
+ and $f0
+ or b
+ ld [$ffa4], a
+ ld a, [$ffa3]
+ and $f
+ ld b, a
+ ld a, [$ffa2]
+ swap a
+ ld [$ffa2], a
+ and $f0
+ or b
+ ld [$ffa3], a
+ ld a, [$ffa2]
+ and $f
+ ld [$ffa2], a
+ ret
+
+Func_f800: ; f800 (3:7800)
+ ld bc, $3
+.asm_f803
+ ld de, $ff9f
+ ld hl, $ffa2
+ push bc
+ call StringCmp
+ pop bc
+ ret c
+ inc b
+ ld de, $ffa1
+ ld hl, $ffa4
+ push bc
+ call SubBCD
+ pop bc
+ jr .asm_f803
+
+
+AddBCDPredef::
+ call GetPredefRegisters
+
+AddBCD::
+ and a
+ ld b, c
+.add
+ ld a, [de]
+ adc [hl]
+ daa
+ ld [de], a
+ dec de
+ dec hl
+ dec c
+ jr nz, .add
+ jr nc, .done
+ ld a, $99
+ inc de
+.fill
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .fill
+.done
+ ret
+
+
+SubBCDPredef::
+ call GetPredefRegisters
+
+SubBCD::
+ and a
+ ld b, c
+.sub
+ ld a, [de]
+ sbc [hl]
+ daa
+ ld [de], a
+ dec de
+ dec hl
+ dec c
+ jr nz, .sub
+ jr nc, .done
+ ld a, $00
+ inc de
+.fill
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .fill
+ scf
+.done
+ ret
+
+
+InitPlayerData:
+InitPlayerData2:
+
+ call Random
+ ld a, [hRandomSub]
+ ld [wPlayerID], a
+
+ call Random
+ ld a, [hRandomAdd]
+ ld [wPlayerID + 1], a
+
+ ld a, $ff
+ ld [wd71b], a ; XXX what's this?
+
+ ld hl, wPartyCount
+ call InitializeEmptyList
+ ld hl, W_NUMINBOX
+ call InitializeEmptyList
+ ld hl, wNumBagItems
+ call InitializeEmptyList
+ ld hl, wNumBoxItems
+ call InitializeEmptyList
+
+START_MONEY EQU $3000
+ ld hl, wPlayerMoney + 1
+ ld a, START_MONEY / $100
+ ld [hld], a
+ xor a
+ ld [hli], a
+ inc hl
+ ld [hl], a
+
+ ld [wcc49], a
+
+ ld hl, W_OBTAINEDBADGES
+ ld [hli], a
+
+ ld [hl], a
+
+ ld hl, wPlayerCoins
+ ld [hli], a
+ ld [hl], a
+
+ ld hl, W_GAMEPROGRESSFLAGS
+ ld bc, $c8
+ call FillMemory ; clear all game progress flags
+
+ jp InitializeMissableObjectsFlags
+
+InitializeEmptyList:
+ xor a ; count
+ ld [hli], a
+ dec a ; terminator
+ ld [hl], a
+ ret
+
+
+IsItemInBag_: ; f8a5 (3:78a5)
+ call GetPredefRegisters
+ ld hl, wNumBagItems ; wNumBagItems
+.asm_f8ab
+ inc hl
+ ld a, [hli]
+ cp $ff
+ jr z, .asm_f8b7
+ cp b
+ jr nz, .asm_f8ab
+ ld a, [hl]
+ ld b, a
+ ret
+.asm_f8b7
+ ld b, $0
+ ret
+
+FindPathToPlayer: ; f8ba (3:78ba)
+ xor a
+ ld hl, $ff97
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld hl, wNPCMovementDirections2
+ ld de, $0
+.loop
+ ld a, [$ff99]
+ ld b, a
+ ld a, [$ff95] ; Y distance in steps
+ call CalcDifference
+ ld d, a
+ and a
+ jr nz, .asm_f8da
+ ld a, [$ff98]
+ set 0, a
+ ld [$ff98], a
+.asm_f8da
+ ld a, [$ff9a]
+ ld b, a
+ ld a, [$ff96] ; X distance in steps
+ call CalcDifference
+ ld e, a
+ and a
+ jr nz, .asm_f8ec
+ ld a, [$ff98]
+ set 1, a
+ ld [$ff98], a
+.asm_f8ec
+ ld a, [$ff98]
+ cp $3
+ jr z, .done
+ ld a, e
+ cp d
+ jr c, .asm_f90a
+ ld a, [$ff9d]
+ bit 1, a
+ jr nz, .asm_f900
+ ld d, NPC_MOVEMENT_RIGHT
+ jr .asm_f902
+.asm_f900
+ ld d, NPC_MOVEMENT_LEFT
+.asm_f902
+ ld a, [$ff9a]
+ add $1
+ ld [$ff9a], a
+ jr .asm_f91c
+.asm_f90a
+ ld a, [$ff9d]
+ bit 0, a
+ jr nz, .asm_f914
+ ld d, NPC_MOVEMENT_DOWN
+ jr .asm_f916
+.asm_f914
+ ld d, NPC_MOVEMENT_UP
+.asm_f916
+ ld a, [$ff99]
+ add $1
+ ld [$ff99], a
+.asm_f91c
+ ld a, d
+ ld [hli], a
+ ld a, [$ff97]
+ inc a
+ ld [$ff97], a
+ jp .loop
+.done
+ ld [hl], $ff
+ ret
+
+CalcPositionOfPlayerRelativeToNPC: ; f929 (3:7929)
+ xor a
+ ld [$ff9d], a
+ ld a, [wSpriteStateData1 + 4] ; player's sprite screen Y position in pixels
+ ld d, a
+ ld a, [wSpriteStateData1 + 6] ; player's sprite screen X position in pixels
+ ld e, a
+ ld hl, wSpriteStateData1
+ ld a, [$ff95] ; sprite offset
+ add l
+ add $4
+ ld l, a
+ jr nc, .noCarry
+ inc h
+.noCarry
+ ld a, d
+ ld b, a
+ ld a, [hli] ; NPC sprite screen Y position in pixels
+ call CalcDifference
+ jr nc, .NPCSouthOfOrAlignedWithPlayer
+.NPCNorthOfPlayer
+ push hl
+ ld hl, $ff9d
+ bit 0, [hl]
+ set 0, [hl]
+ pop hl
+ jr .divideYDistance
+.NPCSouthOfOrAlignedWithPlayer
+ push hl
+ ld hl, $ff9d
+ bit 0, [hl]
+ res 0, [hl]
+ pop hl
+.divideYDistance
+ push hl
+ ld hl, $ffe5
+ ld [hli], a
+ ld a, 16
+ ld [hli], a
+ call DivideBytes ; divide Y absolute distance by 16
+ ld a, [hl] ; quotient
+ ld [$ff95], a
+ pop hl
+ inc hl
+ ld b, e
+ ld a, [hl] ; NPC sprite screen X position in pixels
+ call CalcDifference
+ jr nc, .NPCEastOfOrAlignedWithPlayer
+.NPCWestOfPlayer
+ push hl
+ ld hl, $ff9d
+ bit 1, [hl]
+ set 1, [hl]
+ pop hl
+ jr .divideXDistance
+.NPCEastOfOrAlignedWithPlayer
+ push hl
+ ld hl, $ff9d
+ bit 1, [hl]
+ res 1, [hl]
+ pop hl
+.divideXDistance
+ ld [$ffe5], a
+ ld a, 16
+ ld [$ffe6], a
+ call DivideBytes ; divide X absolute distance by 16
+ ld a, [$ffe7] ; quotient
+ ld [$ff96], a
+ ld a, [$ff9b]
+ and a
+ ret z
+ ld a, [$ff9d]
+ cpl
+ and $3
+ ld [$ff9d], a
+ ret
+
+ConvertNPCMovementDirectionsToJoypadMasks: ; f9a0 (3:79a0)
+ ld a, [$ff95]
+ ld [wNPCMovementDirections2Index], a
+ dec a
+ ld de, wSimulatedJoypadStatesEnd
+ ld hl, wNPCMovementDirections2
+ add l
+ ld l, a
+ jr nc, .loop
+ inc h
+.loop
+ ld a, [hld]
+ call ConvertNPCMovementDirectionToJoypadMask
+ ld [de], a
+ inc de
+ ld a, [$ff95]
+ dec a
+ ld [$ff95], a
+ jr nz, .loop
+ ret
+
+ConvertNPCMovementDirectionToJoypadMask: ; f9bf (3:79bf)
+ push hl
+ ld b, a
+ ld hl, NPCMovementDirectionsToJoypadMasksTable
+.loop
+ ld a, [hli]
+ cp $ff
+ jr z, .done
+ cp b
+ jr z, .loadJoypadMask
+ inc hl
+ jr .loop
+.loadJoypadMask
+ ld a, [hl]
+.done
+ pop hl
+ ret
+
+NPCMovementDirectionsToJoypadMasksTable: ; f9d2 (3:79d2)
+ db NPC_MOVEMENT_UP, D_UP
+ db NPC_MOVEMENT_DOWN, D_DOWN
+ db NPC_MOVEMENT_LEFT, D_LEFT
+ db NPC_MOVEMENT_RIGHT, D_RIGHT
+ db $ff
+
+Func_f9db: ; f9db (3:79db)
+ ret
+
+INCLUDE "engine/hp_bar.asm"
+
+INCLUDE "engine/hidden_object_functions3.asm"
+
+
+SECTION "NPC Sprites 1", ROMX, BANK[NPC_SPRITES_1]
+
+OakAideSprite: INCBIN "gfx/sprites/oak_aide.2bpp"
+RockerSprite: INCBIN "gfx/sprites/rocker.2bpp"
+SwimmerSprite: INCBIN "gfx/sprites/swimmer.2bpp"
+WhitePlayerSprite: INCBIN "gfx/sprites/white_player.2bpp"
+GymHelperSprite: INCBIN "gfx/sprites/gym_helper.2bpp"
+OldPersonSprite: INCBIN "gfx/sprites/old_person.2bpp"
+MartGuySprite: INCBIN "gfx/sprites/mart_guy.2bpp"
+FisherSprite: INCBIN "gfx/sprites/fisher.2bpp"
+OldMediumWomanSprite: INCBIN "gfx/sprites/old_medium_woman.2bpp"
+NurseSprite: INCBIN "gfx/sprites/nurse.2bpp"
+CableClubWomanSprite: INCBIN "gfx/sprites/cable_club_woman.2bpp"
+MrMasterballSprite: INCBIN "gfx/sprites/mr_masterball.2bpp"
+LaprasGiverSprite: INCBIN "gfx/sprites/lapras_giver.2bpp"
+WardenSprite: INCBIN "gfx/sprites/warden.2bpp"
+SsCaptainSprite: INCBIN "gfx/sprites/ss_captain.2bpp"
+Fisher2Sprite: INCBIN "gfx/sprites/fisher2.2bpp"
+BlackbeltSprite: INCBIN "gfx/sprites/blackbelt.2bpp"
+GuardSprite: INCBIN "gfx/sprites/guard.2bpp"
+BallSprite: INCBIN "gfx/sprites/ball.2bpp"
+OmanyteSprite: INCBIN "gfx/sprites/omanyte.2bpp"
+BoulderSprite: INCBIN "gfx/sprites/boulder.2bpp"
+PaperSheetSprite: INCBIN "gfx/sprites/paper_sheet.2bpp"
+BookMapDexSprite: INCBIN "gfx/sprites/book_map_dex.2bpp"
+ClipboardSprite: INCBIN "gfx/sprites/clipboard.2bpp"
+SnorlaxSprite: INCBIN "gfx/sprites/snorlax.2bpp"
+OldAmberSprite: INCBIN "gfx/sprites/old_amber.2bpp"
+LyingOldManSprite: INCBIN "gfx/sprites/lying_old_man.2bpp"
+
+
+SECTION "Graphics", ROMX, BANK[GFX]
+
+PokemonLogoGraphics: INCBIN "gfx/pokemon_logo.2bpp"
+FontGraphics: INCBIN "gfx/font.1bpp"
+ABTiles: INCBIN "gfx/AB.2bpp"
+HpBarAndStatusGraphics: INCBIN "gfx/hp_bar_and_status.2bpp"
+BattleHudTiles1: INCBIN "gfx/battle_hud1.1bpp"
+BattleHudTiles2: INCBIN "gfx/battle_hud2.1bpp"
+BattleHudTiles3: INCBIN "gfx/battle_hud3.1bpp"
+NintendoCopyrightLogoGraphics: INCBIN "gfx/copyright.2bpp"
+GamefreakLogoGraphics: INCBIN "gfx/gamefreak.2bpp"
+TextBoxGraphics: INCBIN "gfx/text_box.2bpp"
+PokedexTileGraphics: INCBIN "gfx/pokedex.2bpp"
+WorldMapTileGraphics: INCBIN "gfx/town_map.2bpp"
+PlayerCharacterTitleGraphics: INCBIN "gfx/player_title.2bpp"
+
+
+SECTION "Battle (bank 4)", ROMX, BANK[$4]
+
+INCLUDE "engine/overworld/is_player_just_outside_map.asm"
+INCLUDE "engine/menu/status_screen.asm"
+INCLUDE "engine/menu/party_menu.asm"
+
+RedPicFront:: INCBIN "pic/trainer/red.pic"
+ShrinkPic1:: INCBIN "pic/trainer/shrink1.pic"
+ShrinkPic2:: INCBIN "pic/trainer/shrink2.pic"
+
+INCLUDE "engine/turn_sprite.asm"
+INCLUDE "engine/menu/start_sub_menus.asm"
+INCLUDE "engine/items/tms.asm"
+INCLUDE "engine/battle/end_of_battle.asm"
+INCLUDE "engine/battle/wild_encounters.asm"
+INCLUDE "engine/battle/moveEffects/recoil_effect.asm"
+INCLUDE "engine/battle/moveEffects/conversion_effect.asm"
+INCLUDE "engine/battle/moveEffects/haze_effect.asm"
+INCLUDE "engine/battle/get_trainer_name.asm"
+
+
+SECTION "NPC Sprites 2", ROMX, BANK[NPC_SPRITES_2]
+
+RedCyclingSprite: INCBIN "gfx/sprites/cycling.2bpp"
+RedSprite: INCBIN "gfx/sprites/red.2bpp"
+BlueSprite: INCBIN "gfx/sprites/blue.2bpp"
+OakSprite: INCBIN "gfx/sprites/oak.2bpp"
+BugCatcherSprite: INCBIN "gfx/sprites/bug_catcher.2bpp"
+SlowbroSprite: INCBIN "gfx/sprites/slowbro.2bpp"
+LassSprite: INCBIN "gfx/sprites/lass.2bpp"
+BlackHairBoy1Sprite: INCBIN "gfx/sprites/black_hair_boy_1.2bpp"
+LittleGirlSprite: INCBIN "gfx/sprites/little_girl.2bpp"
+BirdSprite: INCBIN "gfx/sprites/bird.2bpp"
+FatBaldGuySprite: INCBIN "gfx/sprites/fat_bald_guy.2bpp"
+GamblerSprite: INCBIN "gfx/sprites/gambler.2bpp"
+BlackHairBoy2Sprite: INCBIN "gfx/sprites/black_hair_boy_2.2bpp"
+GirlSprite: INCBIN "gfx/sprites/girl.2bpp"
+HikerSprite: INCBIN "gfx/sprites/hiker.2bpp"
+FoulardWomanSprite: INCBIN "gfx/sprites/foulard_woman.2bpp"
+GentlemanSprite: INCBIN "gfx/sprites/gentleman.2bpp"
+DaisySprite: INCBIN "gfx/sprites/daisy.2bpp"
+BikerSprite: INCBIN "gfx/sprites/biker.2bpp"
+SailorSprite: INCBIN "gfx/sprites/sailor.2bpp"
+CookSprite: INCBIN "gfx/sprites/cook.2bpp"
+BikeShopGuySprite: INCBIN "gfx/sprites/bike_shop_guy.2bpp"
+MrFujiSprite: INCBIN "gfx/sprites/mr_fuji.2bpp"
+GiovanniSprite: INCBIN "gfx/sprites/giovanni.2bpp"
+RocketSprite: INCBIN "gfx/sprites/rocket.2bpp"
+MediumSprite: INCBIN "gfx/sprites/medium.2bpp"
+WaiterSprite: INCBIN "gfx/sprites/waiter.2bpp"
+ErikaSprite: INCBIN "gfx/sprites/erika.2bpp"
+MomGeishaSprite: INCBIN "gfx/sprites/mom_geisha.2bpp"
+BrunetteGirlSprite: INCBIN "gfx/sprites/brunette_girl.2bpp"
+LanceSprite: INCBIN "gfx/sprites/lance.2bpp"
+MomSprite: INCBIN "gfx/sprites/mom.2bpp"
+BaldingGuySprite: INCBIN "gfx/sprites/balding_guy.2bpp"
+YoungBoySprite: INCBIN "gfx/sprites/young_boy.2bpp"
+GameboyKidSprite: INCBIN "gfx/sprites/gameboy_kid.2bpp"
+ClefairySprite: INCBIN "gfx/sprites/clefairy.2bpp"
+AgathaSprite: INCBIN "gfx/sprites/agatha.2bpp"
+BrunoSprite: INCBIN "gfx/sprites/bruno.2bpp"
+LoreleiSprite: INCBIN "gfx/sprites/lorelei.2bpp"
+SeelSprite: INCBIN "gfx/sprites/seel.2bpp"
+
+
+SECTION "Battle (bank 5)", ROMX, BANK[$5]
+
+INCLUDE "engine/load_pokedex_tiles.asm"
+INCLUDE "engine/overworld/map_sprites.asm"
+INCLUDE "engine/overworld/emotion_bubbles.asm"
+INCLUDE "engine/evolve_trade.asm"
+INCLUDE "engine/battle/moveEffects/substitute_effect.asm"
+INCLUDE "engine/menu/pc.asm"
+
+
+SECTION "bank6",ROMX,BANK[$6]
+
+INCLUDE "data/mapHeaders/celadoncity.asm"
+INCLUDE "data/mapObjects/celadoncity.asm"
+CeladonCityBlocks: INCBIN "maps/celadoncity.blk"
+
+INCLUDE "data/mapHeaders/pallettown.asm"
+INCLUDE "data/mapObjects/pallettown.asm"
+PalletTownBlocks: INCBIN "maps/pallettown.blk"
+
+INCLUDE "data/mapHeaders/viridiancity.asm"
+INCLUDE "data/mapObjects/viridiancity.asm"
+ViridianCityBlocks: INCBIN "maps/viridiancity.blk"
+
+INCLUDE "data/mapHeaders/pewtercity.asm"
+INCLUDE "data/mapObjects/pewtercity.asm"
+PewterCityBlocks: INCBIN "maps/pewtercity.blk"
+
+INCLUDE "data/mapHeaders/ceruleancity.asm"
+INCLUDE "data/mapObjects/ceruleancity.asm"
+CeruleanCityBlocks: INCBIN "maps/ceruleancity.blk"
+
+INCLUDE "data/mapHeaders/vermilioncity.asm"
+INCLUDE "data/mapObjects/vermilioncity.asm"
+VermilionCityBlocks: INCBIN "maps/vermilioncity.blk"
+
+INCLUDE "data/mapHeaders/fuchsiacity.asm"
+INCLUDE "data/mapObjects/fuchsiacity.asm"
+FuchsiaCityBlocks: INCBIN "maps/fuchsiacity.blk"
+
+INCLUDE "engine/play_time.asm"
+
+INCLUDE "scripts/pallettown.asm"
+INCLUDE "scripts/viridiancity.asm"
+INCLUDE "scripts/pewtercity.asm"
+INCLUDE "scripts/ceruleancity.asm"
+INCLUDE "scripts/vermilioncity.asm"
+INCLUDE "scripts/celadoncity.asm"
+INCLUDE "scripts/fuchsiacity.asm"
+
+INCLUDE "data/mapHeaders/blueshouse.asm"
+INCLUDE "scripts/blueshouse.asm"
+INCLUDE "data/mapObjects/blueshouse.asm"
+BluesHouseBlocks: INCBIN "maps/blueshouse.blk"
+
+INCLUDE "data/mapHeaders/vermilionhouse3.asm"
+INCLUDE "scripts/vermilionhouse3.asm"
+INCLUDE "data/mapObjects/vermilionhouse3.asm"
+VermilionHouse3Blocks: INCBIN "maps/vermilionhouse3.blk"
+
+INCLUDE "data/mapHeaders/indigoplateaulobby.asm"
+INCLUDE "scripts/indigoplateaulobby.asm"
+INCLUDE "data/mapObjects/indigoplateaulobby.asm"
+IndigoPlateauLobbyBlocks: INCBIN "maps/indigoplateaulobby.blk"
+
+INCLUDE "data/mapHeaders/silphco4.asm"
+INCLUDE "scripts/silphco4.asm"
+INCLUDE "data/mapObjects/silphco4.asm"
+SilphCo4Blocks: INCBIN "maps/silphco4.blk"
+
+INCLUDE "data/mapHeaders/silphco5.asm"
+INCLUDE "scripts/silphco5.asm"
+INCLUDE "data/mapObjects/silphco5.asm"
+SilphCo5Blocks: INCBIN "maps/silphco5.blk"
+
+INCLUDE "data/mapHeaders/silphco6.asm"
+INCLUDE "scripts/silphco6.asm"
+INCLUDE "data/mapObjects/silphco6.asm"
+SilphCo6Blocks: INCBIN "maps/silphco6.blk"
+
+INCLUDE "engine/overworld/npc_movement.asm"
+INCLUDE "engine/overworld/doors.asm"
+INCLUDE "engine/overworld/ledges.asm"
+
+
+SECTION "bank7",ROMX,BANK[$7]
+
+INCLUDE "data/mapHeaders/cinnabarisland.asm"
+INCLUDE "data/mapObjects/cinnabarisland.asm"
+CinnabarIslandBlocks: INCBIN "maps/cinnabarisland.blk"
+
+INCLUDE "data/mapHeaders/route1.asm"
+INCLUDE "data/mapObjects/route1.asm"
+Route1Blocks: INCBIN "maps/route1.blk"
+
+UndergroundPathEntranceRoute8Blocks: INCBIN "maps/undergroundpathentranceroute8.blk"
+
+OaksLabBlocks: INCBIN "maps/oakslab.blk"
+
+Route16HouseBlocks:
+Route2HouseBlocks:
+SaffronHouse1Blocks:
+SaffronHouse2Blocks:
+VermilionHouse1Blocks:
+NameRaterBlocks:
+LavenderHouse1Blocks:
+LavenderHouse2Blocks:
+CeruleanHouse1Blocks:
+PewterHouse1Blocks:
+PewterHouse2Blocks:
+ViridianHouseBlocks: INCBIN "maps/viridianhouse.blk"
+
+CeladonMansion5Blocks:
+SchoolBlocks: INCBIN "maps/school.blk"
+
+CeruleanHouseTrashedBlocks: INCBIN "maps/ceruleanhousetrashed.blk"
+
+DiglettsCaveEntranceRoute11Blocks:
+DiglettsCaveRoute2Blocks: INCBIN "maps/diglettscaveroute2.blk"
+
+INCLUDE "text/monster_names.asm"
+
+INCLUDE "engine/clear_save.asm"
+
+INCLUDE "engine/predefs7.asm"
+
+INCLUDE "scripts/cinnabarisland.asm"
+
+INCLUDE "scripts/route1.asm"
+
+INCLUDE "data/mapHeaders/oakslab.asm"
+INCLUDE "scripts/oakslab.asm"
+INCLUDE "data/mapObjects/oakslab.asm"
+
+INCLUDE "data/mapHeaders/viridianmart.asm"
+INCLUDE "scripts/viridianmart.asm"
+INCLUDE "data/mapObjects/viridianmart.asm"
+ViridianMartBlocks: INCBIN "maps/viridianmart.blk"
+
+INCLUDE "data/mapHeaders/school.asm"
+INCLUDE "scripts/school.asm"
+INCLUDE "data/mapObjects/school.asm"
+
+INCLUDE "data/mapHeaders/viridianhouse.asm"
+INCLUDE "scripts/viridianhouse.asm"
+INCLUDE "data/mapObjects/viridianhouse.asm"
+
+INCLUDE "data/mapHeaders/pewterhouse1.asm"
+INCLUDE "scripts/pewterhouse1.asm"
+INCLUDE "data/mapObjects/pewterhouse1.asm"
+
+INCLUDE "data/mapHeaders/pewterhouse2.asm"
+INCLUDE "scripts/pewterhouse2.asm"
+INCLUDE "data/mapObjects/pewterhouse2.asm"
+
+INCLUDE "data/mapHeaders/ceruleanhousetrashed.asm"
+INCLUDE "scripts/ceruleanhousetrashed.asm"
+INCLUDE "data/mapObjects/ceruleanhousetrashed.asm"
+
+INCLUDE "data/mapHeaders/ceruleanhouse1.asm"
+INCLUDE "scripts/ceruleanhouse1.asm"
+INCLUDE "data/mapObjects/ceruleanhouse1.asm"
+
+INCLUDE "data/mapHeaders/bikeshop.asm"
+INCLUDE "scripts/bikeshop.asm"
+INCLUDE "data/mapObjects/bikeshop.asm"
+BikeShopBlocks: INCBIN "maps/bikeshop.blk"
+
+INCLUDE "data/mapHeaders/lavenderhouse1.asm"
+INCLUDE "scripts/lavenderhouse1.asm"
+INCLUDE "data/mapObjects/lavenderhouse1.asm"
+
+INCLUDE "data/mapHeaders/lavenderhouse2.asm"
+INCLUDE "scripts/lavenderhouse2.asm"
+INCLUDE "data/mapObjects/lavenderhouse2.asm"
+
+INCLUDE "data/mapHeaders/namerater.asm"
+INCLUDE "scripts/namerater.asm"
+INCLUDE "data/mapObjects/namerater.asm"
+
+INCLUDE "data/mapHeaders/vermilionhouse1.asm"
+INCLUDE "scripts/vermilionhouse1.asm"
+INCLUDE "data/mapObjects/vermilionhouse1.asm"
+
+INCLUDE "data/mapHeaders/vermiliondock.asm"
+INCLUDE "scripts/vermiliondock.asm"
+INCLUDE "data/mapObjects/vermiliondock.asm"
+VermilionDockBlocks: INCBIN "maps/vermiliondock.blk"
+
+INCLUDE "data/mapHeaders/celadonmansion5.asm"
+INCLUDE "scripts/celadonmansion5.asm"
+INCLUDE "data/mapObjects/celadonmansion5.asm"
+
+INCLUDE "data/mapHeaders/fuchsiamart.asm"
+INCLUDE "scripts/fuchsiamart.asm"
+INCLUDE "data/mapObjects/fuchsiamart.asm"
+FuchsiaMartBlocks: INCBIN "maps/fuchsiamart.blk"
+
+INCLUDE "data/mapHeaders/saffronhouse1.asm"
+INCLUDE "scripts/saffronhouse1.asm"
+INCLUDE "data/mapObjects/saffronhouse1.asm"
+
+INCLUDE "data/mapHeaders/saffronhouse2.asm"
+INCLUDE "scripts/saffronhouse2.asm"
+INCLUDE "data/mapObjects/saffronhouse2.asm"
+
+INCLUDE "data/mapHeaders/diglettscaveroute2.asm"
+INCLUDE "scripts/diglettscaveroute2.asm"
+INCLUDE "data/mapObjects/diglettscaveroute2.asm"
+
+INCLUDE "data/mapHeaders/route2house.asm"
+INCLUDE "scripts/route2house.asm"
+INCLUDE "data/mapObjects/route2house.asm"
+
+INCLUDE "data/mapHeaders/route5gate.asm"
+INCLUDE "scripts/route5gate.asm"
+INCLUDE "data/mapObjects/route5gate.asm"
+Route5GateBlocks: INCBIN "maps/route5gate.blk"
+
+INCLUDE "data/mapHeaders/route6gate.asm"
+INCLUDE "scripts/route6gate.asm"
+INCLUDE "data/mapObjects/route6gate.asm"
+Route6GateBlocks: INCBIN "maps/route6gate.blk"
+
+INCLUDE "data/mapHeaders/route7gate.asm"
+INCLUDE "scripts/route7gate.asm"
+INCLUDE "data/mapObjects/route7gate.asm"
+Route7GateBlocks: INCBIN "maps/route7gate.blk"
+
+INCLUDE "data/mapHeaders/route8gate.asm"
+INCLUDE "scripts/route8gate.asm"
+INCLUDE "data/mapObjects/route8gate.asm"
+Route8GateBlocks: INCBIN "maps/route8gate.blk"
+
+INCLUDE "data/mapHeaders/undergroundpathentranceroute8.asm"
+INCLUDE "scripts/undergroundpathentranceroute8.asm"
+INCLUDE "data/mapObjects/undergroundpathentranceroute8.asm"
+
+INCLUDE "data/mapHeaders/powerplant.asm"
+INCLUDE "scripts/powerplant.asm"
+INCLUDE "data/mapObjects/powerplant.asm"
+PowerPlantBlocks: INCBIN "maps/powerplant.blk"
+
+INCLUDE "data/mapHeaders/diglettscaveroute11.asm"
+INCLUDE "scripts/diglettscaveroute11.asm"
+INCLUDE "data/mapObjects/diglettscaveroute11.asm"
+
+INCLUDE "data/mapHeaders/route16house.asm"
+INCLUDE "scripts/route16house.asm"
+INCLUDE "data/mapObjects/route16house.asm"
+
+INCLUDE "data/mapHeaders/route22gate.asm"
+INCLUDE "scripts/route22gate.asm"
+INCLUDE "data/mapObjects/route22gate.asm"
+Route22GateBlocks: INCBIN "maps/route22gate.blk"
+
+INCLUDE "data/mapHeaders/billshouse.asm"
+INCLUDE "scripts/billshouse.asm"
+INCLUDE "data/mapObjects/billshouse.asm"
+BillsHouseBlocks: INCBIN "maps/billshouse.blk"
+IF DEF(_OPTION_BEACH_HOUSE)
+INCLUDE "data/mapHeaders/beach_house.asm"
+INCLUDE "scripts/beach_house.asm"
+BeachHouseBlockdata: INCBIN "maps/beach_house.blk"
+INCLUDE "data/mapObjects/beach_house.asm"
+ENDC
+
+INCLUDE "engine/menu/oaks_pc.asm"
+
+INCLUDE "engine/hidden_object_functions7.asm"
+
+
+SECTION "Pics 1", ROMX, BANK[PICS_1]
+
+RhydonPicFront:: INCBIN "pic/bmon/rhydon.pic"
+RhydonPicBack:: INCBIN "pic/monback/rhydonb.pic"
+KangaskhanPicFront:: INCBIN "pic/bmon/kangaskhan.pic"
+KangaskhanPicBack:: INCBIN "pic/monback/kangaskhanb.pic"
+NidoranMPicFront:: INCBIN "pic/bmon/nidoranm.pic"
+NidoranMPicBack:: INCBIN "pic/monback/nidoranmb.pic"
+ClefairyPicFront:: INCBIN "pic/bmon/clefairy.pic"
+ClefairyPicBack:: INCBIN "pic/monback/clefairyb.pic"
+SpearowPicFront:: INCBIN "pic/bmon/spearow.pic"
+SpearowPicBack:: INCBIN "pic/monback/spearowb.pic"
+VoltorbPicFront:: INCBIN "pic/bmon/voltorb.pic"
+VoltorbPicBack:: INCBIN "pic/monback/voltorbb.pic"
+NidokingPicFront:: INCBIN "pic/bmon/nidoking.pic"
+NidokingPicBack:: INCBIN "pic/monback/nidokingb.pic"
+SlowbroPicFront:: INCBIN "pic/bmon/slowbro.pic"
+SlowbroPicBack:: INCBIN "pic/monback/slowbrob.pic"
+IvysaurPicFront:: INCBIN "pic/bmon/ivysaur.pic"
+IvysaurPicBack:: INCBIN "pic/monback/ivysaurb.pic"
+ExeggutorPicFront:: INCBIN "pic/bmon/exeggutor.pic"
+ExeggutorPicBack:: INCBIN "pic/monback/exeggutorb.pic"
+LickitungPicFront:: INCBIN "pic/bmon/lickitung.pic"
+LickitungPicBack:: INCBIN "pic/monback/lickitungb.pic"
+ExeggcutePicFront:: INCBIN "pic/bmon/exeggcute.pic"
+ExeggcutePicBack:: INCBIN "pic/monback/exeggcuteb.pic"
+GrimerPicFront:: INCBIN "pic/bmon/grimer.pic"
+GrimerPicBack:: INCBIN "pic/monback/grimerb.pic"
+GengarPicFront:: INCBIN "pic/bmon/gengar.pic"
+GengarPicBack:: INCBIN "pic/monback/gengarb.pic"
+NidoranFPicFront:: INCBIN "pic/bmon/nidoranf.pic"
+NidoranFPicBack:: INCBIN "pic/monback/nidoranfb.pic"
+NidoqueenPicFront:: INCBIN "pic/bmon/nidoqueen.pic"
+NidoqueenPicBack:: INCBIN "pic/monback/nidoqueenb.pic"
+CubonePicFront:: INCBIN "pic/bmon/cubone.pic"
+CubonePicBack:: INCBIN "pic/monback/cuboneb.pic"
+RhyhornPicFront:: INCBIN "pic/bmon/rhyhorn.pic"
+RhyhornPicBack:: INCBIN "pic/monback/rhyhornb.pic"
+LaprasPicFront:: INCBIN "pic/bmon/lapras.pic"
+LaprasPicBack:: INCBIN "pic/monback/laprasb.pic"
+ArcaninePicFront:: INCBIN "pic/bmon/arcanine.pic"
+ArcaninePicBack:: INCBIN "pic/monback/arcanineb.pic"
+GyaradosPicFront:: INCBIN "pic/bmon/gyarados.pic"
+GyaradosPicBack:: INCBIN "pic/monback/gyaradosb.pic"
+ShellderPicFront:: INCBIN "pic/bmon/shellder.pic"
+ShellderPicBack:: INCBIN "pic/monback/shellderb.pic"
+TentacoolPicFront:: INCBIN "pic/bmon/tentacool.pic"
+TentacoolPicBack:: INCBIN "pic/monback/tentacoolb.pic"
+GastlyPicFront:: INCBIN "pic/bmon/gastly.pic"
+GastlyPicBack:: INCBIN "pic/monback/gastlyb.pic"
+ScytherPicFront:: INCBIN "pic/bmon/scyther.pic"
+ScytherPicBack:: INCBIN "pic/monback/scytherb.pic"
+StaryuPicFront:: INCBIN "pic/bmon/staryu.pic"
+StaryuPicBack:: INCBIN "pic/monback/staryub.pic"
+BlastoisePicFront:: INCBIN "pic/bmon/blastoise.pic"
+BlastoisePicBack:: INCBIN "pic/monback/blastoiseb.pic"
+PinsirPicFront:: INCBIN "pic/bmon/pinsir.pic"
+PinsirPicBack:: INCBIN "pic/monback/pinsirb.pic"
+TangelaPicFront:: INCBIN "pic/bmon/tangela.pic"
+TangelaPicBack:: INCBIN "pic/monback/tangelab.pic"
+
+
+SECTION "Battle (bank 9)", ROMX, BANK[$9]
+INCLUDE "engine/battle/print_type.asm"
+INCLUDE "engine/battle/save_trainer_name.asm"
+INCLUDE "engine/battle/moveEffects/focus_energy_effect.asm"
+
+
+SECTION "Pics 2", ROMX, BANK[PICS_2]
+
+GrowlithePicFront:: INCBIN "pic/bmon/growlithe.pic"
+GrowlithePicBack:: INCBIN "pic/monback/growlitheb.pic"
+OnixPicFront:: INCBIN "pic/bmon/onix.pic"
+OnixPicBack:: INCBIN "pic/monback/onixb.pic"
+FearowPicFront:: INCBIN "pic/bmon/fearow.pic"
+FearowPicBack:: INCBIN "pic/monback/fearowb.pic"
+PidgeyPicFront:: INCBIN "pic/bmon/pidgey.pic"
+PidgeyPicBack:: INCBIN "pic/monback/pidgeyb.pic"
+SlowpokePicFront:: INCBIN "pic/bmon/slowpoke.pic"
+SlowpokePicBack:: INCBIN "pic/monback/slowpokeb.pic"
+KadabraPicFront:: INCBIN "pic/bmon/kadabra.pic"
+KadabraPicBack:: INCBIN "pic/monback/kadabrab.pic"
+GravelerPicFront:: INCBIN "pic/bmon/graveler.pic"
+GravelerPicBack:: INCBIN "pic/monback/gravelerb.pic"
+ChanseyPicFront:: INCBIN "pic/bmon/chansey.pic"
+ChanseyPicBack:: INCBIN "pic/monback/chanseyb.pic"
+MachokePicFront:: INCBIN "pic/bmon/machoke.pic"
+MachokePicBack:: INCBIN "pic/monback/machokeb.pic"
+MrMimePicFront:: INCBIN "pic/bmon/mr.mime.pic"
+MrMimePicBack:: INCBIN "pic/monback/mr.mimeb.pic"
+HitmonleePicFront:: INCBIN "pic/bmon/hitmonlee.pic"
+HitmonleePicBack:: INCBIN "pic/monback/hitmonleeb.pic"
+HitmonchanPicFront:: INCBIN "pic/bmon/hitmonchan.pic"
+HitmonchanPicBack:: INCBIN "pic/monback/hitmonchanb.pic"
+ArbokPicFront:: INCBIN "pic/bmon/arbok.pic"
+ArbokPicBack:: INCBIN "pic/monback/arbokb.pic"
+ParasectPicFront:: INCBIN "pic/bmon/parasect.pic"
+ParasectPicBack:: INCBIN "pic/monback/parasectb.pic"
+PsyduckPicFront:: INCBIN "pic/bmon/psyduck.pic"
+PsyduckPicBack:: INCBIN "pic/monback/psyduckb.pic"
+DrowzeePicFront:: INCBIN "pic/bmon/drowzee.pic"
+DrowzeePicBack:: INCBIN "pic/monback/drowzeeb.pic"
+GolemPicFront:: INCBIN "pic/bmon/golem.pic"
+GolemPicBack:: INCBIN "pic/monback/golemb.pic"
+MagmarPicFront:: INCBIN "pic/bmon/magmar.pic"
+MagmarPicBack:: INCBIN "pic/monback/magmarb.pic"
+ElectabuzzPicFront:: INCBIN "pic/bmon/electabuzz.pic"
+ElectabuzzPicBack:: INCBIN "pic/monback/electabuzzb.pic"
+MagnetonPicFront:: INCBIN "pic/bmon/magneton.pic"
+MagnetonPicBack:: INCBIN "pic/monback/magnetonb.pic"
+KoffingPicFront:: INCBIN "pic/bmon/koffing.pic"
+KoffingPicBack:: INCBIN "pic/monback/koffingb.pic"
+MankeyPicFront:: INCBIN "pic/bmon/mankey.pic"
+MankeyPicBack:: INCBIN "pic/monback/mankeyb.pic"
+SeelPicFront:: INCBIN "pic/bmon/seel.pic"
+SeelPicBack:: INCBIN "pic/monback/seelb.pic"
+DiglettPicFront:: INCBIN "pic/bmon/diglett.pic"
+DiglettPicBack:: INCBIN "pic/monback/diglettb.pic"
+TaurosPicFront:: INCBIN "pic/bmon/tauros.pic"
+TaurosPicBack:: INCBIN "pic/monback/taurosb.pic"
+FarfetchdPicFront:: INCBIN "pic/bmon/farfetchd.pic"
+FarfetchdPicBack:: INCBIN "pic/monback/farfetchdb.pic"
+VenonatPicFront:: INCBIN "pic/bmon/venonat.pic"
+VenonatPicBack:: INCBIN "pic/monback/venonatb.pic"
+DragonitePicFront:: INCBIN "pic/bmon/dragonite.pic"
+DragonitePicBack:: INCBIN "pic/monback/dragoniteb.pic"
+DoduoPicFront:: INCBIN "pic/bmon/doduo.pic"
+DoduoPicBack:: INCBIN "pic/monback/doduob.pic"
+PoliwagPicFront:: INCBIN "pic/bmon/poliwag.pic"
+PoliwagPicBack:: INCBIN "pic/monback/poliwagb.pic"
+JynxPicFront:: INCBIN "pic/bmon/jynx.pic"
+JynxPicBack:: INCBIN "pic/monback/jynxb.pic"
+MoltresPicFront:: INCBIN "pic/bmon/moltres.pic"
+MoltresPicBack:: INCBIN "pic/monback/moltresb.pic"
+
+
+SECTION "Battle (bank A)", ROMX, BANK[$A]
+INCLUDE "engine/battle/moveEffects/leech_seed_effect.asm"
+
+
+SECTION "Pics 3", ROMX, BANK[PICS_3]
+
+ArticunoPicFront:: INCBIN "pic/bmon/articuno.pic"
+ArticunoPicBack:: INCBIN "pic/monback/articunob.pic"
+ZapdosPicFront:: INCBIN "pic/bmon/zapdos.pic"
+ZapdosPicBack:: INCBIN "pic/monback/zapdosb.pic"
+DittoPicFront:: INCBIN "pic/bmon/ditto.pic"
+DittoPicBack:: INCBIN "pic/monback/dittob.pic"
+MeowthPicFront:: INCBIN "pic/bmon/meowth.pic"
+MeowthPicBack:: INCBIN "pic/monback/meowthb.pic"
+KrabbyPicFront:: INCBIN "pic/bmon/krabby.pic"
+KrabbyPicBack:: INCBIN "pic/monback/krabbyb.pic"
+VulpixPicFront:: INCBIN "pic/bmon/vulpix.pic"
+VulpixPicBack:: INCBIN "pic/monback/vulpixb.pic"
+NinetalesPicFront:: INCBIN "pic/bmon/ninetales.pic"
+NinetalesPicBack:: INCBIN "pic/monback/ninetalesb.pic"
+PikachuPicFront:: INCBIN "pic/bmon/pikachu.pic"
+PikachuPicBack:: INCBIN "pic/monback/pikachub.pic"
+RaichuPicFront:: INCBIN "pic/bmon/raichu.pic"
+RaichuPicBack:: INCBIN "pic/monback/raichub.pic"
+DratiniPicFront:: INCBIN "pic/bmon/dratini.pic"
+DratiniPicBack:: INCBIN "pic/monback/dratinib.pic"
+DragonairPicFront:: INCBIN "pic/bmon/dragonair.pic"
+DragonairPicBack:: INCBIN "pic/monback/dragonairb.pic"
+KabutoPicFront:: INCBIN "pic/bmon/kabuto.pic"
+KabutoPicBack:: INCBIN "pic/monback/kabutob.pic"
+KabutopsPicFront:: INCBIN "pic/bmon/kabutops.pic"
+KabutopsPicBack:: INCBIN "pic/monback/kabutopsb.pic"
+HorseaPicFront:: INCBIN "pic/bmon/horsea.pic"
+HorseaPicBack:: INCBIN "pic/monback/horseab.pic"
+SeadraPicFront:: INCBIN "pic/bmon/seadra.pic"
+SeadraPicBack:: INCBIN "pic/monback/seadrab.pic"
+SandshrewPicFront:: INCBIN "pic/bmon/sandshrew.pic"
+SandshrewPicBack:: INCBIN "pic/monback/sandshrewb.pic"
+SandslashPicFront:: INCBIN "pic/bmon/sandslash.pic"
+SandslashPicBack:: INCBIN "pic/monback/sandslashb.pic"
+OmanytePicFront:: INCBIN "pic/bmon/omanyte.pic"
+OmanytePicBack:: INCBIN "pic/monback/omanyteb.pic"
+OmastarPicFront:: INCBIN "pic/bmon/omastar.pic"
+OmastarPicBack:: INCBIN "pic/monback/omastarb.pic"
+JigglypuffPicFront:: INCBIN "pic/bmon/jigglypuff.pic"
+JigglypuffPicBack:: INCBIN "pic/monback/jigglypuffb.pic"
+WigglytuffPicFront:: INCBIN "pic/bmon/wigglytuff.pic"
+WigglytuffPicBack:: INCBIN "pic/monback/wigglytuffb.pic"
+EeveePicFront:: INCBIN "pic/bmon/eevee.pic"
+EeveePicBack:: INCBIN "pic/monback/eeveeb.pic"
+FlareonPicFront:: INCBIN "pic/bmon/flareon.pic"
+FlareonPicBack:: INCBIN "pic/monback/flareonb.pic"
+JolteonPicFront:: INCBIN "pic/bmon/jolteon.pic"
+JolteonPicBack:: INCBIN "pic/monback/jolteonb.pic"
+VaporeonPicFront:: INCBIN "pic/bmon/vaporeon.pic"
+VaporeonPicBack:: INCBIN "pic/monback/vaporeonb.pic"
+MachopPicFront:: INCBIN "pic/bmon/machop.pic"
+MachopPicBack:: INCBIN "pic/monback/machopb.pic"
+ZubatPicFront:: INCBIN "pic/bmon/zubat.pic"
+ZubatPicBack:: INCBIN "pic/monback/zubatb.pic"
+EkansPicFront:: INCBIN "pic/bmon/ekans.pic"
+EkansPicBack:: INCBIN "pic/monback/ekansb.pic"
+ParasPicFront:: INCBIN "pic/bmon/paras.pic"
+ParasPicBack:: INCBIN "pic/monback/parasb.pic"
+PoliwhirlPicFront:: INCBIN "pic/bmon/poliwhirl.pic"
+PoliwhirlPicBack:: INCBIN "pic/monback/poliwhirlb.pic"
+PoliwrathPicFront:: INCBIN "pic/bmon/poliwrath.pic"
+PoliwrathPicBack:: INCBIN "pic/monback/poliwrathb.pic"
+WeedlePicFront:: INCBIN "pic/bmon/weedle.pic"
+WeedlePicBack:: INCBIN "pic/monback/weedleb.pic"
+KakunaPicFront:: INCBIN "pic/bmon/kakuna.pic"
+KakunaPicBack:: INCBIN "pic/monback/kakunab.pic"
+BeedrillPicFront:: INCBIN "pic/bmon/beedrill.pic"
+BeedrillPicBack:: INCBIN "pic/monback/beedrillb.pic"
+
+FossilKabutopsPic:: INCBIN "pic/bmon/fossilkabutops.pic"
+
+
+SECTION "Battle (bank B)", ROMX, BANK[$B]
+
+INCLUDE "engine/battle/display_effectiveness.asm"
+
+TrainerInfoTextBoxTileGraphics: INCBIN "gfx/trainer_info.2bpp"
+BlankLeaderNames: INCBIN "gfx/blank_leader_names.2bpp"
+CircleTile: INCBIN "gfx/circle_tile.2bpp"
+BadgeNumbersTileGraphics: INCBIN "gfx/badge_numbers.2bpp"
+
+INCLUDE "engine/items/tmhm.asm"
+INCLUDE "engine/battle/scale_sprites.asm"
+INCLUDE "engine/battle/moveEffects/pay_day_effect.asm"
+INCLUDE "engine/game_corner_slots2.asm"
+
+
+SECTION "Pics 4", ROMX, BANK[PICS_4]
+
+DodrioPicFront:: INCBIN "pic/bmon/dodrio.pic"
+DodrioPicBack:: INCBIN "pic/monback/dodriob.pic"
+PrimeapePicFront:: INCBIN "pic/bmon/primeape.pic"
+PrimeapePicBack:: INCBIN "pic/monback/primeapeb.pic"
+DugtrioPicFront:: INCBIN "pic/bmon/dugtrio.pic"
+DugtrioPicBack:: INCBIN "pic/monback/dugtriob.pic"
+VenomothPicFront:: INCBIN "pic/bmon/venomoth.pic"
+VenomothPicBack:: INCBIN "pic/monback/venomothb.pic"
+DewgongPicFront:: INCBIN "pic/bmon/dewgong.pic"
+DewgongPicBack:: INCBIN "pic/monback/dewgongb.pic"
+CaterpiePicFront:: INCBIN "pic/bmon/caterpie.pic"
+CaterpiePicBack:: INCBIN "pic/monback/caterpieb.pic"
+MetapodPicFront:: INCBIN "pic/bmon/metapod.pic"
+MetapodPicBack:: INCBIN "pic/monback/metapodb.pic"
+ButterfreePicFront:: INCBIN "pic/bmon/butterfree.pic"
+ButterfreePicBack:: INCBIN "pic/monback/butterfreeb.pic"
+MachampPicFront:: INCBIN "pic/bmon/machamp.pic"
+MachampPicBack:: INCBIN "pic/monback/machampb.pic"
+GolduckPicFront:: INCBIN "pic/bmon/golduck.pic"
+GolduckPicBack:: INCBIN "pic/monback/golduckb.pic"
+HypnoPicFront:: INCBIN "pic/bmon/hypno.pic"
+HypnoPicBack:: INCBIN "pic/monback/hypnob.pic"
+GolbatPicFront:: INCBIN "pic/bmon/golbat.pic"
+GolbatPicBack:: INCBIN "pic/monback/golbatb.pic"
+MewtwoPicFront:: INCBIN "pic/bmon/mewtwo.pic"
+MewtwoPicBack:: INCBIN "pic/monback/mewtwob.pic"
+SnorlaxPicFront:: INCBIN "pic/bmon/snorlax.pic"
+SnorlaxPicBack:: INCBIN "pic/monback/snorlaxb.pic"
+MagikarpPicFront:: INCBIN "pic/bmon/magikarp.pic"
+MagikarpPicBack:: INCBIN "pic/monback/magikarpb.pic"
+MukPicFront:: INCBIN "pic/bmon/muk.pic"
+MukPicBack:: INCBIN "pic/monback/mukb.pic"
+KinglerPicFront:: INCBIN "pic/bmon/kingler.pic"
+KinglerPicBack:: INCBIN "pic/monback/kinglerb.pic"
+CloysterPicFront:: INCBIN "pic/bmon/cloyster.pic"
+CloysterPicBack:: INCBIN "pic/monback/cloysterb.pic"
+ElectrodePicFront:: INCBIN "pic/bmon/electrode.pic"
+ElectrodePicBack:: INCBIN "pic/monback/electrodeb.pic"
+ClefablePicFront:: INCBIN "pic/bmon/clefable.pic"
+ClefablePicBack:: INCBIN "pic/monback/clefableb.pic"
+WeezingPicFront:: INCBIN "pic/bmon/weezing.pic"
+WeezingPicBack:: INCBIN "pic/monback/weezingb.pic"
+PersianPicFront:: INCBIN "pic/bmon/persian.pic"
+PersianPicBack:: INCBIN "pic/monback/persianb.pic"
+MarowakPicFront:: INCBIN "pic/bmon/marowak.pic"
+MarowakPicBack:: INCBIN "pic/monback/marowakb.pic"
+HaunterPicFront:: INCBIN "pic/bmon/haunter.pic"
+HaunterPicBack:: INCBIN "pic/monback/haunterb.pic"
+AbraPicFront:: INCBIN "pic/bmon/abra.pic"
+AbraPicBack:: INCBIN "pic/monback/abrab.pic"
+AlakazamPicFront:: INCBIN "pic/bmon/alakazam.pic"
+AlakazamPicBack:: INCBIN "pic/monback/alakazamb.pic"
+PidgeottoPicFront:: INCBIN "pic/bmon/pidgeotto.pic"
+PidgeottoPicBack:: INCBIN "pic/monback/pidgeottob.pic"
+PidgeotPicFront:: INCBIN "pic/bmon/pidgeot.pic"
+PidgeotPicBack:: INCBIN "pic/monback/pidgeotb.pic"
+StarmiePicFront:: INCBIN "pic/bmon/starmie.pic"
+StarmiePicBack:: INCBIN "pic/monback/starmieb.pic"
+
+RedPicBack:: INCBIN "pic/trainer/redb.pic"
+OldManPic:: INCBIN "pic/trainer/oldman.pic"
+
+
+SECTION "Battle (bank C)", ROMX, BANK[$C]
+INCLUDE "engine/battle/moveEffects/mist_effect.asm"
+INCLUDE "engine/battle/moveEffects/one_hit_ko_effect.asm"
+
+
+SECTION "Pics 5", ROMX, BANK[PICS_5]
+
+BulbasaurPicFront:: INCBIN "pic/bmon/bulbasaur.pic"
+BulbasaurPicBack:: INCBIN "pic/monback/bulbasaurb.pic"
+VenusaurPicFront:: INCBIN "pic/bmon/venusaur.pic"
+VenusaurPicBack:: INCBIN "pic/monback/venusaurb.pic"
+TentacruelPicFront:: INCBIN "pic/bmon/tentacruel.pic"
+TentacruelPicBack:: INCBIN "pic/monback/tentacruelb.pic"
+GoldeenPicFront:: INCBIN "pic/bmon/goldeen.pic"
+GoldeenPicBack:: INCBIN "pic/monback/goldeenb.pic"
+SeakingPicFront:: INCBIN "pic/bmon/seaking.pic"
+SeakingPicBack:: INCBIN "pic/monback/seakingb.pic"
+PonytaPicFront:: INCBIN "pic/bmon/ponyta.pic"
+RapidashPicFront:: INCBIN "pic/bmon/rapidash.pic"
+PonytaPicBack:: INCBIN "pic/monback/ponytab.pic"
+RapidashPicBack:: INCBIN "pic/monback/rapidashb.pic"
+RattataPicFront:: INCBIN "pic/bmon/rattata.pic"
+RattataPicBack:: INCBIN "pic/monback/rattatab.pic"
+RaticatePicFront:: INCBIN "pic/bmon/raticate.pic"
+RaticatePicBack:: INCBIN "pic/monback/raticateb.pic"
+NidorinoPicFront:: INCBIN "pic/bmon/nidorino.pic"
+NidorinoPicBack:: INCBIN "pic/monback/nidorinob.pic"
+NidorinaPicFront:: INCBIN "pic/bmon/nidorina.pic"
+NidorinaPicBack:: INCBIN "pic/monback/nidorinab.pic"
+GeodudePicFront:: INCBIN "pic/bmon/geodude.pic"
+GeodudePicBack:: INCBIN "pic/monback/geodudeb.pic"
+PorygonPicFront:: INCBIN "pic/bmon/porygon.pic"
+PorygonPicBack:: INCBIN "pic/monback/porygonb.pic"
+AerodactylPicFront:: INCBIN "pic/bmon/aerodactyl.pic"
+AerodactylPicBack:: INCBIN "pic/monback/aerodactylb.pic"
+MagnemitePicFront:: INCBIN "pic/bmon/magnemite.pic"
+MagnemitePicBack:: INCBIN "pic/monback/magnemiteb.pic"
+CharmanderPicFront:: INCBIN "pic/bmon/charmander.pic"
+CharmanderPicBack:: INCBIN "pic/monback/charmanderb.pic"
+SquirtlePicFront:: INCBIN "pic/bmon/squirtle.pic"
+SquirtlePicBack:: INCBIN "pic/monback/squirtleb.pic"
+CharmeleonPicFront:: INCBIN "pic/bmon/charmeleon.pic"
+CharmeleonPicBack:: INCBIN "pic/monback/charmeleonb.pic"
+WartortlePicFront:: INCBIN "pic/bmon/wartortle.pic"
+WartortlePicBack:: INCBIN "pic/monback/wartortleb.pic"
+CharizardPicFront:: INCBIN "pic/bmon/charizard.pic"
+CharizardPicBack:: INCBIN "pic/monback/charizardb.pic"
+FossilAerodactylPic:: INCBIN "pic/bmon/fossilaerodactyl.pic"
+GhostPic:: INCBIN "pic/other/ghost.pic"
+OddishPicFront:: INCBIN "pic/bmon/oddish.pic"
+OddishPicBack:: INCBIN "pic/monback/oddishb.pic"
+GloomPicFront:: INCBIN "pic/bmon/gloom.pic"
+GloomPicBack:: INCBIN "pic/monback/gloomb.pic"
+VileplumePicFront:: INCBIN "pic/bmon/vileplume.pic"
+VileplumePicBack:: INCBIN "pic/monback/vileplumeb.pic"
+BellsproutPicFront:: INCBIN "pic/bmon/bellsprout.pic"
+BellsproutPicBack:: INCBIN "pic/monback/bellsproutb.pic"
+WeepinbellPicFront:: INCBIN "pic/bmon/weepinbell.pic"
+WeepinbellPicBack:: INCBIN "pic/monback/weepinbellb.pic"
+VictreebelPicFront:: INCBIN "pic/bmon/victreebel.pic"
+VictreebelPicBack:: INCBIN "pic/monback/victreebelb.pic"
+
+
+SECTION "Battle (bank D)", ROMX, BANK[$D]
+
+INCLUDE "engine/titlescreen2.asm"
+INCLUDE "engine/battle/link_battle_versus_text.asm"
+INCLUDE "engine/slot_machine.asm"
+INCLUDE "engine/overworld/pewter_guys.asm"
+INCLUDE "engine/multiply_divide.asm"
+INCLUDE "engine/game_corner_slots.asm"
+
+
+SECTION "bankE",ROMX,BANK[$E]
+
+INCLUDE "data/moves.asm"
+BaseStats: INCLUDE "data/base_stats.asm"
+INCLUDE "data/cries.asm"
+INCLUDE "engine/battle/unused_stats_functions.asm"
+INCLUDE "engine/battle/scroll_draw_trainer_pic.asm"
+INCLUDE "engine/battle/trainer_ai.asm"
+INCLUDE "engine/battle/draw_hud_pokeball_gfx.asm"
+
+TradingAnimationGraphics:
+ INCBIN "gfx/game_boy.norepeat.2bpp"
+ INCBIN "gfx/link_cable.2bpp"
+
+TradingAnimationGraphics2:
+; Pokeball traveling through the link cable.
+ INCBIN "gfx/trade2.2bpp"
+
+INCLUDE "engine/evos_moves.asm"
+INCLUDE "engine/battle/moveEffects/heal_effect.asm"
+INCLUDE "engine/battle/moveEffects/transform_effect.asm"
+INCLUDE "engine/battle/moveEffects/reflect_light_screen_effect.asm"
+
+
+SECTION "bankF",ROMX,BANK[$F]
+
+INCLUDE "engine/battle/core.asm"
+
+
+SECTION "bank10",ROMX,BANK[$10]
+
+INCLUDE "engine/menu/pokedex.asm"
+INCLUDE "engine/trade.asm"
+INCLUDE "engine/intro.asm"
+INCLUDE "engine/trade2.asm"
+
+
+SECTION "bank11",ROMX,BANK[$11]
+
+INCLUDE "data/mapHeaders/lavendertown.asm"
+INCLUDE "data/mapObjects/lavendertown.asm"
+LavenderTownBlocks: INCBIN "maps/lavendertown.blk"
+
+ViridianPokecenterBlocks: INCBIN "maps/viridianpokecenter.blk"
+
+SafariZoneRestHouse1Blocks:
+SafariZoneRestHouse2Blocks:
+SafariZoneRestHouse3Blocks:
+SafariZoneRestHouse4Blocks: INCBIN "maps/safarizoneresthouse1.blk"
+
+INCLUDE "scripts/lavendertown.asm"
+
+INCLUDE "engine/pokedex_rating.asm"
+
+INCLUDE "data/mapHeaders/viridianpokecenter.asm"
+INCLUDE "scripts/viridianpokecenter.asm"
+INCLUDE "data/mapObjects/viridianpokecenter.asm"
+
+INCLUDE "data/mapHeaders/mansion1.asm"
+INCLUDE "scripts/mansion1.asm"
+INCLUDE "data/mapObjects/mansion1.asm"
+Mansion1Blocks: INCBIN "maps/mansion1.blk"
+
+INCLUDE "data/mapHeaders/rocktunnel1.asm"
+INCLUDE "scripts/rocktunnel1.asm"
+INCLUDE "data/mapObjects/rocktunnel1.asm"
+RockTunnel1Blocks: INCBIN "maps/rocktunnel1.blk"
+
+INCLUDE "data/mapHeaders/seafoamislands1.asm"
+INCLUDE "scripts/seafoamislands1.asm"
+INCLUDE "data/mapObjects/seafoamislands1.asm"
+SeafoamIslands1Blocks: INCBIN "maps/seafoamislands1.blk"
+
+INCLUDE "data/mapHeaders/ssanne3.asm"
+INCLUDE "scripts/ssanne3.asm"
+INCLUDE "data/mapObjects/ssanne3.asm"
+SSAnne3Blocks: INCBIN "maps/ssanne3.blk"
+
+INCLUDE "data/mapHeaders/victoryroad3.asm"
+INCLUDE "scripts/victoryroad3.asm"
+INCLUDE "data/mapObjects/victoryroad3.asm"
+VictoryRoad3Blocks: INCBIN "maps/victoryroad3.blk"
+
+INCLUDE "data/mapHeaders/rockethideout1.asm"
+INCLUDE "scripts/rockethideout1.asm"
+INCLUDE "data/mapObjects/rockethideout1.asm"
+RocketHideout1Blocks: INCBIN "maps/rockethideout1.blk"
+
+INCLUDE "data/mapHeaders/rockethideout2.asm"
+INCLUDE "scripts/rockethideout2.asm"
+INCLUDE "data/mapObjects/rockethideout2.asm"
+RocketHideout2Blocks: INCBIN "maps/rockethideout2.blk"
+
+INCLUDE "data/mapHeaders/rockethideout3.asm"
+INCLUDE "scripts/rockethideout3.asm"
+INCLUDE "data/mapObjects/rockethideout3.asm"
+RocketHideout3Blocks: INCBIN "maps/rockethideout3.blk"
+
+INCLUDE "data/mapHeaders/rockethideout4.asm"
+INCLUDE "scripts/rockethideout4.asm"
+INCLUDE "data/mapObjects/rockethideout4.asm"
+RocketHideout4Blocks: INCBIN "maps/rockethideout4.blk"
+
+INCLUDE "data/mapHeaders/rockethideoutelevator.asm"
+INCLUDE "scripts/rockethideoutelevator.asm"
+INCLUDE "data/mapObjects/rockethideoutelevator.asm"
+RocketHideoutElevatorBlocks: INCBIN "maps/rockethideoutelevator.blk"
+
+INCLUDE "data/mapHeaders/silphcoelevator.asm"
+INCLUDE "scripts/silphcoelevator.asm"
+INCLUDE "data/mapObjects/silphcoelevator.asm"
+SilphCoElevatorBlocks: INCBIN "maps/silphcoelevator.blk"
+
+INCLUDE "data/mapHeaders/safarizoneeast.asm"
+INCLUDE "scripts/safarizoneeast.asm"
+INCLUDE "data/mapObjects/safarizoneeast.asm"
+SafariZoneEastBlocks: INCBIN "maps/safarizoneeast.blk"
+
+INCLUDE "data/mapHeaders/safarizonenorth.asm"
+INCLUDE "scripts/safarizonenorth.asm"
+INCLUDE "data/mapObjects/safarizonenorth.asm"
+SafariZoneNorthBlocks: INCBIN "maps/safarizonenorth.blk"
+
+INCLUDE "data/mapHeaders/safarizonecenter.asm"
+INCLUDE "scripts/safarizonecenter.asm"
+INCLUDE "data/mapObjects/safarizonecenter.asm"
+SafariZoneCenterBlocks: INCBIN "maps/safarizonecenter.blk"
+
+INCLUDE "data/mapHeaders/safarizoneresthouse1.asm"
+INCLUDE "scripts/safarizoneresthouse1.asm"
+INCLUDE "data/mapObjects/safarizoneresthouse1.asm"
+
+INCLUDE "data/mapHeaders/safarizoneresthouse2.asm"
+INCLUDE "scripts/safarizoneresthouse2.asm"
+INCLUDE "data/mapObjects/safarizoneresthouse2.asm"
+
+INCLUDE "data/mapHeaders/safarizoneresthouse3.asm"
+INCLUDE "scripts/safarizoneresthouse3.asm"
+INCLUDE "data/mapObjects/safarizoneresthouse3.asm"
+
+INCLUDE "data/mapHeaders/safarizoneresthouse4.asm"
+INCLUDE "scripts/safarizoneresthouse4.asm"
+INCLUDE "data/mapObjects/safarizoneresthouse4.asm"
+
+INCLUDE "data/mapHeaders/unknowndungeon2.asm"
+INCLUDE "scripts/unknowndungeon2.asm"
+INCLUDE "data/mapObjects/unknowndungeon2.asm"
+UnknownDungeon2Blocks: INCBIN "maps/unknowndungeon2.blk"
+
+INCLUDE "data/mapHeaders/unknowndungeon3.asm"
+INCLUDE "scripts/unknowndungeon3.asm"
+INCLUDE "data/mapObjects/unknowndungeon3.asm"
+UnknownDungeon3Blocks: INCBIN "maps/unknowndungeon3.blk"
+
+INCLUDE "data/mapHeaders/rocktunnel2.asm"
+INCLUDE "scripts/rocktunnel2.asm"
+INCLUDE "data/mapObjects/rocktunnel2.asm"
+RockTunnel2Blocks: INCBIN "maps/rocktunnel2.blk"
+
+INCLUDE "data/mapHeaders/seafoamislands2.asm"
+INCLUDE "scripts/seafoamislands2.asm"
+INCLUDE "data/mapObjects/seafoamislands2.asm"
+SeafoamIslands2Blocks: INCBIN "maps/seafoamislands2.blk"
+
+INCLUDE "data/mapHeaders/seafoamislands3.asm"
+INCLUDE "scripts/seafoamislands3.asm"
+INCLUDE "data/mapObjects/seafoamislands3.asm"
+SeafoamIslands3Blocks: INCBIN "maps/seafoamislands3.blk"
+
+INCLUDE "data/mapHeaders/seafoamislands4.asm"
+INCLUDE "scripts/seafoamislands4.asm"
+INCLUDE "data/mapObjects/seafoamislands4.asm"
+SeafoamIslands4Blocks: INCBIN "maps/seafoamislands4.blk"
+
+INCLUDE "data/mapHeaders/seafoamislands5.asm"
+INCLUDE "scripts/seafoamislands5.asm"
+INCLUDE "data/mapObjects/seafoamislands5.asm"
+SeafoamIslands5Blocks: INCBIN "maps/seafoamislands5.blk"
+
+INCLUDE "engine/overworld/hidden_objects.asm"
+
+
+SECTION "bank12",ROMX,BANK[$12]
+
+INCLUDE "data/mapHeaders/route7.asm"
+INCLUDE "data/mapObjects/route7.asm"
+Route7Blocks: INCBIN "maps/route7.blk"
+
+CeladonPokecenterBlocks:
+RockTunnelPokecenterBlocks:
+MtMoonPokecenterBlocks: INCBIN "maps/mtmoonpokecenter.blk"
+
+Route18GateBlocks:
+Route15GateBlocks:
+Route11GateBlocks: INCBIN "maps/route11gate.blk"
+
+Route18GateUpstairsBlocks:
+Route16GateUpstairsBlocks:
+Route12GateUpstairsBlocks:
+Route15GateUpstairsBlocks:
+Route11GateUpstairsBlocks: INCBIN "maps/route11gateupstairs.blk"
+
+INCLUDE "engine/predefs12.asm"
+
+INCLUDE "scripts/route7.asm"
+
+INCLUDE "data/mapHeaders/redshouse1f.asm"
+INCLUDE "scripts/redshouse1f.asm"
+INCLUDE "data/mapObjects/redshouse1f.asm"
+RedsHouse1FBlocks: INCBIN "maps/redshouse1f.blk"
+
+INCLUDE "data/mapHeaders/celadonmart3.asm"
+INCLUDE "scripts/celadonmart3.asm"
+INCLUDE "data/mapObjects/celadonmart3.asm"
+CeladonMart3Blocks: INCBIN "maps/celadonmart3.blk"
+
+INCLUDE "data/mapHeaders/celadonmart4.asm"
+INCLUDE "scripts/celadonmart4.asm"
+INCLUDE "data/mapObjects/celadonmart4.asm"
+CeladonMart4Blocks: INCBIN "maps/celadonmart4.blk"
+
+INCLUDE "data/mapHeaders/celadonmartroof.asm"
+INCLUDE "scripts/celadonmartroof.asm"
+INCLUDE "data/mapObjects/celadonmartroof.asm"
+CeladonMartRoofBlocks: INCBIN "maps/celadonmartroof.blk"
+
+INCLUDE "data/mapHeaders/celadonmartelevator.asm"
+INCLUDE "scripts/celadonmartelevator.asm"
+INCLUDE "data/mapObjects/celadonmartelevator.asm"
+CeladonMartElevatorBlocks: INCBIN "maps/celadonmartelevator.blk"
+
+INCLUDE "data/mapHeaders/celadonmansion1.asm"
+INCLUDE "scripts/celadonmansion1.asm"
+INCLUDE "data/mapObjects/celadonmansion1.asm"
+CeladonMansion1Blocks: INCBIN "maps/celadonmansion1.blk"
+
+INCLUDE "data/mapHeaders/celadonmansion2.asm"
+INCLUDE "scripts/celadonmansion2.asm"
+INCLUDE "data/mapObjects/celadonmansion2.asm"
+CeladonMansion2Blocks: INCBIN "maps/celadonmansion2.blk"
+
+INCLUDE "data/mapHeaders/celadonmansion3.asm"
+INCLUDE "scripts/celadonmansion3.asm"
+INCLUDE "data/mapObjects/celadonmansion3.asm"
+CeladonMansion3Blocks: INCBIN "maps/celadonmansion3.blk"
+
+INCLUDE "data/mapHeaders/celadonmansion4.asm"
+INCLUDE "scripts/celadonmansion4.asm"
+INCLUDE "data/mapObjects/celadonmansion4.asm"
+CeladonMansion4Blocks: INCBIN "maps/celadonmansion4.blk"
+
+INCLUDE "data/mapHeaders/celadonpokecenter.asm"
+INCLUDE "scripts/celadonpokecenter.asm"
+INCLUDE "data/mapObjects/celadonpokecenter.asm"
+
+INCLUDE "data/mapHeaders/celadongym.asm"
+INCLUDE "scripts/celadongym.asm"
+INCLUDE "data/mapObjects/celadongym.asm"
+CeladonGymBlocks: INCBIN "maps/celadongym.blk"
+
+INCLUDE "data/mapHeaders/celadongamecorner.asm"
+INCLUDE "scripts/celadongamecorner.asm"
+INCLUDE "data/mapObjects/celadongamecorner.asm"
+CeladonGameCornerBlocks: INCBIN "maps/celadongamecorner.blk"
+
+INCLUDE "data/mapHeaders/celadonmart5.asm"
+INCLUDE "scripts/celadonmart5.asm"
+INCLUDE "data/mapObjects/celadonmart5.asm"
+CeladonMart5Blocks: INCBIN "maps/celadonmart5.blk"
+
+INCLUDE "data/mapHeaders/celadonprizeroom.asm"
+INCLUDE "scripts/celadonprizeroom.asm"
+INCLUDE "data/mapObjects/celadonprizeroom.asm"
+CeladonPrizeRoomBlocks: INCBIN "maps/celadonprizeroom.blk"
+
+INCLUDE "data/mapHeaders/celadondiner.asm"
+INCLUDE "scripts/celadondiner.asm"
+INCLUDE "data/mapObjects/celadondiner.asm"
+CeladonDinerBlocks: INCBIN "maps/celadondiner.blk"
+
+INCLUDE "data/mapHeaders/celadonhouse.asm"
+INCLUDE "scripts/celadonhouse.asm"
+INCLUDE "data/mapObjects/celadonhouse.asm"
+CeladonHouseBlocks: INCBIN "maps/celadonhouse.blk"
+
+INCLUDE "data/mapHeaders/celadonhotel.asm"
+INCLUDE "scripts/celadonhotel.asm"
+INCLUDE "data/mapObjects/celadonhotel.asm"
+CeladonHotelBlocks: INCBIN "maps/celadonhotel.blk"
+
+INCLUDE "data/mapHeaders/mtmoonpokecenter.asm"
+INCLUDE "scripts/mtmoonpokecenter.asm"
+INCLUDE "data/mapObjects/mtmoonpokecenter.asm"
+
+INCLUDE "data/mapHeaders/rocktunnelpokecenter.asm"
+INCLUDE "scripts/rocktunnelpokecenter.asm"
+INCLUDE "data/mapObjects/rocktunnelpokecenter.asm"
+
+INCLUDE "data/mapHeaders/route11gate.asm"
+INCLUDE "scripts/route11gate.asm"
+INCLUDE "data/mapObjects/route11gate.asm"
+
+INCLUDE "data/mapHeaders/route11gateupstairs.asm"
+INCLUDE "scripts/route11gateupstairs.asm"
+INCLUDE "data/mapObjects/route11gateupstairs.asm"
+
+INCLUDE "data/mapHeaders/route12gate.asm"
+INCLUDE "scripts/route12gate.asm"
+INCLUDE "data/mapObjects/route12gate.asm"
+Route12GateBlocks: INCBIN "maps/route12gate.blk"
+
+INCLUDE "data/mapHeaders/route12gateupstairs.asm"
+INCLUDE "scripts/route12gateupstairs.asm"
+INCLUDE "data/mapObjects/route12gateupstairs.asm"
+
+INCLUDE "data/mapHeaders/route15gate.asm"
+INCLUDE "scripts/route15gate.asm"
+INCLUDE "data/mapObjects/route15gate.asm"
+
+INCLUDE "data/mapHeaders/route15gateupstairs.asm"
+INCLUDE "scripts/route15gateupstairs.asm"
+INCLUDE "data/mapObjects/route15gateupstairs.asm"
+
+INCLUDE "data/mapHeaders/route16gate.asm"
+INCLUDE "scripts/route16gate.asm"
+INCLUDE "data/mapObjects/route16gate.asm"
+Route16GateBlocks: INCBIN "maps/route16gate.blk"
+
+INCLUDE "data/mapHeaders/route16gateupstairs.asm"
+INCLUDE "scripts/route16gateupstairs.asm"
+INCLUDE "data/mapObjects/route16gateupstairs.asm"
+
+INCLUDE "data/mapHeaders/route18gate.asm"
+INCLUDE "scripts/route18gate.asm"
+INCLUDE "data/mapObjects/route18gate.asm"
+
+INCLUDE "data/mapHeaders/route18gateupstairs.asm"
+INCLUDE "scripts/route18gateupstairs.asm"
+INCLUDE "data/mapObjects/route18gateupstairs.asm"
+
+INCLUDE "data/mapHeaders/mtmoon1.asm"
+INCLUDE "scripts/mtmoon1.asm"
+INCLUDE "data/mapObjects/mtmoon1.asm"
+MtMoon1Blocks: INCBIN "maps/mtmoon1.blk"
+
+INCLUDE "data/mapHeaders/mtmoon3.asm"
+INCLUDE "scripts/mtmoon3.asm"
+INCLUDE "data/mapObjects/mtmoon3.asm"
+MtMoon3Blocks: INCBIN "maps/mtmoon3.blk"
+
+INCLUDE "data/mapHeaders/safarizonewest.asm"
+INCLUDE "scripts/safarizonewest.asm"
+INCLUDE "data/mapObjects/safarizonewest.asm"
+SafariZoneWestBlocks: INCBIN "maps/safarizonewest.blk"
+
+INCLUDE "data/mapHeaders/safarizonesecrethouse.asm"
+INCLUDE "scripts/safarizonesecrethouse.asm"
+INCLUDE "data/mapObjects/safarizonesecrethouse.asm"
+SafariZoneSecretHouseBlocks: INCBIN "maps/safarizonesecrethouse.blk"
+
+
+SECTION "bank13",ROMX,BANK[$13]
+
+TrainerPics::
+YoungsterPic:: INCBIN "pic/trainer/youngster.pic"
+BugCatcherPic:: INCBIN "pic/trainer/bugcatcher.pic"
+LassPic:: INCBIN "pic/trainer/lass.pic"
+SailorPic:: INCBIN "pic/trainer/sailor.pic"
+JrTrainerMPic:: INCBIN "pic/trainer/jr.trainerm.pic"
+JrTrainerFPic:: INCBIN "pic/trainer/jr.trainerf.pic"
+PokemaniacPic:: INCBIN "pic/trainer/pokemaniac.pic"
+SuperNerdPic:: INCBIN "pic/trainer/supernerd.pic"
+HikerPic:: INCBIN "pic/trainer/hiker.pic"
+BikerPic:: INCBIN "pic/trainer/biker.pic"
+BurglarPic:: INCBIN "pic/trainer/burglar.pic"
+EngineerPic:: INCBIN "pic/trainer/engineer.pic"
+FisherPic:: INCBIN "pic/trainer/fisher.pic"
+SwimmerPic:: INCBIN "pic/trainer/swimmer.pic"
+CueBallPic:: INCBIN "pic/trainer/cueball.pic"
+GamblerPic:: INCBIN "pic/trainer/gambler.pic"
+BeautyPic:: INCBIN "pic/trainer/beauty.pic"
+PsychicPic:: INCBIN "pic/trainer/psychic.pic"
+RockerPic:: INCBIN "pic/trainer/rocker.pic"
+JugglerPic:: INCBIN "pic/trainer/juggler.pic"
+TamerPic:: INCBIN "pic/trainer/tamer.pic"
+BirdKeeperPic:: INCBIN "pic/trainer/birdkeeper.pic"
+BlackbeltPic:: INCBIN "pic/trainer/blackbelt.pic"
+Rival1Pic:: INCBIN "pic/trainer/rival1.pic"
+ProfOakPic:: INCBIN "pic/trainer/prof.oak.pic"
+ChiefPic::
+ScientistPic:: INCBIN "pic/trainer/scientist.pic"
+GiovanniPic:: INCBIN "pic/trainer/giovanni.pic"
+RocketPic:: INCBIN "pic/trainer/rocket.pic"
+CooltrainerMPic:: INCBIN "pic/trainer/cooltrainerm.pic"
+CooltrainerFPic:: INCBIN "pic/trainer/cooltrainerf.pic"
+BrunoPic:: INCBIN "pic/trainer/bruno.pic"
+BrockPic:: INCBIN "pic/trainer/brock.pic"
+MistyPic:: INCBIN "pic/trainer/misty.pic"
+LtSurgePic:: INCBIN "pic/trainer/lt.surge.pic"
+ErikaPic:: INCBIN "pic/trainer/erika.pic"
+KogaPic:: INCBIN "pic/trainer/koga.pic"
+BlainePic:: INCBIN "pic/trainer/blaine.pic"
+SabrinaPic:: INCBIN "pic/trainer/sabrina.pic"
+GentlemanPic:: INCBIN "pic/trainer/gentleman.pic"
+Rival2Pic:: INCBIN "pic/trainer/rival2.pic"
+Rival3Pic:: INCBIN "pic/trainer/rival3.pic"
+LoreleiPic:: INCBIN "pic/trainer/lorelei.pic"
+ChannelerPic:: INCBIN "pic/trainer/channeler.pic"
+AgathaPic:: INCBIN "pic/trainer/agatha.pic"
+LancePic:: INCBIN "pic/trainer/lance.pic"
+
+INCLUDE "data/mapHeaders/battlecenterm.asm"
+INCLUDE "scripts/battlecenterm.asm"
+INCLUDE "data/mapObjects/battlecenterm.asm"
+BattleCenterMBlocks: INCBIN "maps/battlecenterm.blk"
+
+INCLUDE "data/mapHeaders/tradecenterm.asm"
+INCLUDE "scripts/tradecenterm.asm"
+INCLUDE "data/mapObjects/tradecenterm.asm"
+TradeCenterMBlocks: INCBIN "maps/tradecenterm.blk"
+
+INCLUDE "engine/give_pokemon.asm"
+
+INCLUDE "engine/predefs.asm"
+
+
+SECTION "bank14",ROMX,BANK[$14]
+
+INCLUDE "data/mapHeaders/route22.asm"
+INCLUDE "data/mapObjects/route22.asm"
+Route22Blocks: INCBIN "maps/route22.blk"
+
+INCLUDE "data/mapHeaders/route20.asm"
+INCLUDE "data/mapObjects/route20.asm"
+Route20Blocks: INCBIN "maps/route20.blk"
+
+INCLUDE "data/mapHeaders/route23.asm"
+INCLUDE "data/mapObjects/route23.asm"
+Route23Blocks: INCBIN "maps/route23.blk"
+
+INCLUDE "data/mapHeaders/route24.asm"
+INCLUDE "data/mapObjects/route24.asm"
+Route24Blocks: INCBIN "maps/route24.blk"
+
+INCLUDE "data/mapHeaders/route25.asm"
+INCLUDE "data/mapObjects/route25.asm"
+Route25Blocks: INCBIN "maps/route25.blk"
+
+INCLUDE "data/mapHeaders/indigoplateau.asm"
+INCLUDE "scripts/indigoplateau.asm"
+INCLUDE "data/mapObjects/indigoplateau.asm"
+IndigoPlateauBlocks: INCBIN "maps/indigoplateau.blk"
+
+INCLUDE "data/mapHeaders/saffroncity.asm"
+INCLUDE "data/mapObjects/saffroncity.asm"
+SaffronCityBlocks: INCBIN "maps/saffroncity.blk"
+INCLUDE "scripts/saffroncity.asm"
+
+INCLUDE "scripts/route20.asm"
+INCLUDE "scripts/route22.asm"
+INCLUDE "scripts/route23.asm"
+INCLUDE "scripts/route24.asm"
+INCLUDE "scripts/route25.asm"
+
+INCLUDE "data/mapHeaders/victoryroad2.asm"
+INCLUDE "scripts/victoryroad2.asm"
+INCLUDE "data/mapObjects/victoryroad2.asm"
+VictoryRoad2Blocks: INCBIN "maps/victoryroad2.blk"
+
+INCLUDE "data/mapHeaders/mtmoon2.asm"
+INCLUDE "scripts/mtmoon2.asm"
+INCLUDE "data/mapObjects/mtmoon2.asm"
+MtMoon2Blocks: INCBIN "maps/mtmoon2.blk"
+
+INCLUDE "data/mapHeaders/silphco7.asm"
+INCLUDE "scripts/silphco7.asm"
+INCLUDE "data/mapObjects/silphco7.asm"
+SilphCo7Blocks: INCBIN "maps/silphco7.blk"
+
+INCLUDE "data/mapHeaders/mansion2.asm"
+INCLUDE "scripts/mansion2.asm"
+INCLUDE "data/mapObjects/mansion2.asm"
+Mansion2Blocks: INCBIN "maps/mansion2.blk"
+
+INCLUDE "data/mapHeaders/mansion3.asm"
+INCLUDE "scripts/mansion3.asm"
+INCLUDE "data/mapObjects/mansion3.asm"
+Mansion3Blocks: INCBIN "maps/mansion3.blk"
+
+INCLUDE "data/mapHeaders/mansion4.asm"
+INCLUDE "scripts/mansion4.asm"
+INCLUDE "data/mapObjects/mansion4.asm"
+Mansion4Blocks: INCBIN "maps/mansion4.blk"
+
+INCLUDE "engine/battle/init_battle_variables.asm"
+INCLUDE "engine/battle/moveEffects/paralyze_effect.asm"
+
+INCLUDE "engine/overworld/card_key.asm"
+
+INCLUDE "engine/menu/prize_menu.asm"
+
+INCLUDE "engine/hidden_object_functions14.asm"
+
+
+SECTION "bank15",ROMX,BANK[$15]
+
+INCLUDE "data/mapHeaders/route2.asm"
+INCLUDE "data/mapObjects/route2.asm"
+Route2Blocks: INCBIN "maps/route2.blk"
+
+INCLUDE "data/mapHeaders/route3.asm"
+INCLUDE "data/mapObjects/route3.asm"
+Route3Blocks: INCBIN "maps/route3.blk"
+
+INCLUDE "data/mapHeaders/route4.asm"
+INCLUDE "data/mapObjects/route4.asm"
+Route4Blocks: INCBIN "maps/route4.blk"
+
+INCLUDE "data/mapHeaders/route5.asm"
+INCLUDE "data/mapObjects/route5.asm"
+Route5Blocks: INCBIN "maps/route5.blk"
+
+INCLUDE "data/mapHeaders/route9.asm"
+INCLUDE "data/mapObjects/route9.asm"
+Route9Blocks: INCBIN "maps/route9.blk"
+
+INCLUDE "data/mapHeaders/route13.asm"
+INCLUDE "data/mapObjects/route13.asm"
+Route13Blocks: INCBIN "maps/route13.blk"
+
+INCLUDE "data/mapHeaders/route14.asm"
+INCLUDE "data/mapObjects/route14.asm"
+Route14Blocks: INCBIN "maps/route14.blk"
+
+INCLUDE "data/mapHeaders/route17.asm"
+INCLUDE "data/mapObjects/route17.asm"
+Route17Blocks: INCBIN "maps/route17.blk"
+
+INCLUDE "data/mapHeaders/route19.asm"
+INCLUDE "data/mapObjects/route19.asm"
+IF DEF(_OPTION_BEACH_HOUSE)
+Route19Blocks: INCBIN "maps/route19-yellow.blk"
+ELSE
+Route19Blocks: INCBIN "maps/route19.blk"
+ENDC
+
+INCLUDE "data/mapHeaders/route21.asm"
+INCLUDE "data/mapObjects/route21.asm"
+Route21Blocks: INCBIN "maps/route21.blk"
+
+VermilionHouse2Blocks:
+Route12HouseBlocks:
+DayCareMBlocks: INCBIN "maps/daycarem.blk"
+
+FuchsiaHouse3Blocks: INCBIN "maps/fuchsiahouse3.blk"
+
+INCLUDE "engine/battle/experience.asm"
+
+INCLUDE "scripts/route2.asm"
+INCLUDE "scripts/route3.asm"
+INCLUDE "scripts/route4.asm"
+INCLUDE "scripts/route5.asm"
+INCLUDE "scripts/route9.asm"
+INCLUDE "scripts/route13.asm"
+INCLUDE "scripts/route14.asm"
+INCLUDE "scripts/route17.asm"
+INCLUDE "scripts/route19.asm"
+INCLUDE "scripts/route21.asm"
+
+INCLUDE "data/mapHeaders/vermilionhouse2.asm"
+INCLUDE "scripts/vermilionhouse2.asm"
+INCLUDE "data/mapObjects/vermilionhouse2.asm"
+
+INCLUDE "data/mapHeaders/celadonmart2.asm"
+INCLUDE "scripts/celadonmart2.asm"
+INCLUDE "data/mapObjects/celadonmart2.asm"
+CeladonMart2Blocks: INCBIN "maps/celadonmart2.blk"
+
+INCLUDE "data/mapHeaders/fuchsiahouse3.asm"
+INCLUDE "scripts/fuchsiahouse3.asm"
+INCLUDE "data/mapObjects/fuchsiahouse3.asm"
+
+INCLUDE "data/mapHeaders/daycarem.asm"
+INCLUDE "scripts/daycarem.asm"
+INCLUDE "data/mapObjects/daycarem.asm"
+
+INCLUDE "data/mapHeaders/route12house.asm"
+INCLUDE "scripts/route12house.asm"
+INCLUDE "data/mapObjects/route12house.asm"
+
+INCLUDE "data/mapHeaders/silphco8.asm"
+INCLUDE "scripts/silphco8.asm"
+INCLUDE "data/mapObjects/silphco8.asm"
+SilphCo8Blocks: INCBIN "maps/silphco8.blk"
+
+INCLUDE "engine/menu/diploma.asm"
+
+INCLUDE "engine/overworld/trainers.asm"
+
+
+SECTION "bank16",ROMX,BANK[$16]
+
+INCLUDE "data/mapHeaders/route6.asm"
+INCLUDE "data/mapObjects/route6.asm"
+Route6Blocks: INCBIN "maps/route6.blk"
+
+INCLUDE "data/mapHeaders/route8.asm"
+INCLUDE "data/mapObjects/route8.asm"
+Route8Blocks: INCBIN "maps/route8.blk"
+
+INCLUDE "data/mapHeaders/route10.asm"
+INCLUDE "data/mapObjects/route10.asm"
+Route10Blocks: INCBIN "maps/route10.blk"
+
+INCLUDE "data/mapHeaders/route11.asm"
+INCLUDE "data/mapObjects/route11.asm"
+Route11Blocks: INCBIN "maps/route11.blk"
+
+INCLUDE "data/mapHeaders/route12.asm"
+INCLUDE "data/mapObjects/route12.asm"
+Route12Blocks: INCBIN "maps/route12.blk"
+
+INCLUDE "data/mapHeaders/route15.asm"
+INCLUDE "data/mapObjects/route15.asm"
+Route15Blocks: INCBIN "maps/route15.blk"
+
+INCLUDE "data/mapHeaders/route16.asm"
+INCLUDE "data/mapObjects/route16.asm"
+Route16Blocks: INCBIN "maps/route16.blk"
+
+INCLUDE "data/mapHeaders/route18.asm"
+INCLUDE "data/mapObjects/route18.asm"
+Route18Blocks: INCBIN "maps/route18.blk"
+
+ INCBIN "maps/unusedblocks58d7d.blk"
+
+INCLUDE "engine/battle/common_text.asm"
+
+INCLUDE "engine/experience.asm"
+
+INCLUDE "engine/overworld/oaks_aide.asm"
+
+INCLUDE "scripts/route6.asm"
+INCLUDE "scripts/route8.asm"
+INCLUDE "scripts/route10.asm"
+INCLUDE "scripts/route11.asm"
+INCLUDE "scripts/route12.asm"
+INCLUDE "scripts/route15.asm"
+INCLUDE "scripts/route16.asm"
+INCLUDE "scripts/route18.asm"
+
+INCLUDE "data/mapHeaders/fanclub.asm"
+INCLUDE "scripts/fanclub.asm"
+INCLUDE "data/mapObjects/fanclub.asm"
+FanClubBlocks:
+ INCBIN "maps/fanclub.blk"
+
+INCLUDE "data/mapHeaders/silphco2.asm"
+INCLUDE "scripts/silphco2.asm"
+INCLUDE "data/mapObjects/silphco2.asm"
+SilphCo2Blocks:
+ INCBIN "maps/silphco2.blk"
+
+INCLUDE "data/mapHeaders/silphco3.asm"
+INCLUDE "scripts/silphco3.asm"
+INCLUDE "data/mapObjects/silphco3.asm"
+SilphCo3Blocks:
+ INCBIN "maps/silphco3.blk"
+
+INCLUDE "data/mapHeaders/silphco10.asm"
+INCLUDE "scripts/silphco10.asm"
+INCLUDE "data/mapObjects/silphco10.asm"
+SilphCo10Blocks:
+ INCBIN "maps/silphco10.blk"
+
+INCLUDE "data/mapHeaders/lance.asm"
+INCLUDE "scripts/lance.asm"
+INCLUDE "data/mapObjects/lance.asm"
+LanceBlocks:
+ INCBIN "maps/lance.blk"
+
+INCLUDE "data/mapHeaders/halloffameroom.asm"
+INCLUDE "scripts/halloffameroom.asm"
+INCLUDE "data/mapObjects/halloffameroom.asm"
+HallofFameRoomBlocks:
+ INCBIN "maps/halloffameroom.blk"
+
+INCLUDE "engine/overworld/saffron_guards.asm"
+
+
+SECTION "bank17",ROMX,BANK[$17]
+
+SaffronMartBlocks:
+LavenderMartBlocks:
+CeruleanMartBlocks:
+VermilionMartBlocks: INCBIN "maps/vermilionmart.blk"
+
+CopycatsHouse2FBlocks:
+RedsHouse2FBlocks: INCBIN "maps/redshouse2f.blk"
+
+Museum1FBlocks: INCBIN "maps/museum1f.blk"
+
+Museum2FBlocks: INCBIN "maps/museum2f.blk"
+
+SaffronPokecenterBlocks:
+VermilionPokecenterBlocks:
+LavenderPokecenterBlocks:
+PewterPokecenterBlocks: INCBIN "maps/pewterpokecenter.blk"
+
+UndergroundPathEntranceRoute7Blocks:
+UndergroundPathEntranceRoute7CopyBlocks:
+UndergroundPathEntranceRoute6Blocks:
+UndergroundPathEntranceRoute5Blocks: INCBIN "maps/undergroundpathentranceroute5.blk"
+
+Route2GateBlocks:
+ViridianForestEntranceBlocks:
+ViridianForestExitBlocks: INCBIN "maps/viridianforestexit.blk"
+
+INCLUDE "data/mapHeaders/redshouse2f.asm"
+INCLUDE "scripts/redshouse2f.asm"
+INCLUDE "data/mapObjects/redshouse2f.asm"
+
+INCLUDE "engine/predefs17.asm"
+
+INCLUDE "data/mapHeaders/museum1f.asm"
+INCLUDE "scripts/museum1f.asm"
+INCLUDE "data/mapObjects/museum1f.asm"
+
+INCLUDE "data/mapHeaders/museum2f.asm"
+INCLUDE "scripts/museum2f.asm"
+INCLUDE "data/mapObjects/museum2f.asm"
+
+INCLUDE "data/mapHeaders/pewtergym.asm"
+INCLUDE "scripts/pewtergym.asm"
+INCLUDE "data/mapObjects/pewtergym.asm"
+PewterGymBlocks: INCBIN "maps/pewtergym.blk"
+
+INCLUDE "data/mapHeaders/pewterpokecenter.asm"
+INCLUDE "scripts/pewterpokecenter.asm"
+INCLUDE "data/mapObjects/pewterpokecenter.asm"
+
+INCLUDE "data/mapHeaders/ceruleanpokecenter.asm"
+INCLUDE "scripts/ceruleanpokecenter.asm"
+INCLUDE "data/mapObjects/ceruleanpokecenter.asm"
+CeruleanPokecenterBlocks: INCBIN "maps/ceruleanpokecenter.blk"
+
+INCLUDE "data/mapHeaders/ceruleangym.asm"
+INCLUDE "scripts/ceruleangym.asm"
+INCLUDE "data/mapObjects/ceruleangym.asm"
+CeruleanGymBlocks: INCBIN "maps/ceruleangym.blk"
+
+INCLUDE "data/mapHeaders/ceruleanmart.asm"
+INCLUDE "scripts/ceruleanmart.asm"
+INCLUDE "data/mapObjects/ceruleanmart.asm"
+
+INCLUDE "data/mapHeaders/lavenderpokecenter.asm"
+INCLUDE "scripts/lavenderpokecenter.asm"
+INCLUDE "data/mapObjects/lavenderpokecenter.asm"
+
+INCLUDE "data/mapHeaders/lavendermart.asm"
+INCLUDE "scripts/lavendermart.asm"
+INCLUDE "data/mapObjects/lavendermart.asm"
+
+INCLUDE "data/mapHeaders/vermilionpokecenter.asm"
+INCLUDE "scripts/vermilionpokecenter.asm"
+INCLUDE "data/mapObjects/vermilionpokecenter.asm"
+
+INCLUDE "data/mapHeaders/vermilionmart.asm"
+INCLUDE "scripts/vermilionmart.asm"
+INCLUDE "data/mapObjects/vermilionmart.asm"
+
+INCLUDE "data/mapHeaders/vermiliongym.asm"
+INCLUDE "scripts/vermiliongym.asm"
+INCLUDE "data/mapObjects/vermiliongym.asm"
+VermilionGymBlocks: INCBIN "maps/vermiliongym.blk"
+
+INCLUDE "data/mapHeaders/copycatshouse2f.asm"
+INCLUDE "scripts/copycatshouse2f.asm"
+INCLUDE "data/mapObjects/copycatshouse2f.asm"
+
+INCLUDE "data/mapHeaders/fightingdojo.asm"
+INCLUDE "scripts/fightingdojo.asm"
+INCLUDE "data/mapObjects/fightingdojo.asm"
+FightingDojoBlocks: INCBIN "maps/fightingdojo.blk"
+
+INCLUDE "data/mapHeaders/saffrongym.asm"
+INCLUDE "scripts/saffrongym.asm"
+INCLUDE "data/mapObjects/saffrongym.asm"
+SaffronGymBlocks: INCBIN "maps/saffrongym.blk"
+
+INCLUDE "data/mapHeaders/saffronmart.asm"
+INCLUDE "scripts/saffronmart.asm"
+INCLUDE "data/mapObjects/saffronmart.asm"
+
+INCLUDE "data/mapHeaders/silphco1.asm"
+INCLUDE "scripts/silphco1.asm"
+INCLUDE "data/mapObjects/silphco1.asm"
+SilphCo1Blocks: INCBIN "maps/silphco1.blk"
+
+INCLUDE "data/mapHeaders/saffronpokecenter.asm"
+INCLUDE "scripts/saffronpokecenter.asm"
+INCLUDE "data/mapObjects/saffronpokecenter.asm"
+
+INCLUDE "data/mapHeaders/viridianforestexit.asm"
+INCLUDE "scripts/viridianforestexit.asm"
+INCLUDE "data/mapObjects/viridianforestexit.asm"
+
+INCLUDE "data/mapHeaders/route2gate.asm"
+INCLUDE "scripts/route2gate.asm"
+INCLUDE "data/mapObjects/route2gate.asm"
+
+INCLUDE "data/mapHeaders/viridianforestentrance.asm"
+INCLUDE "scripts/viridianforestentrance.asm"
+INCLUDE "data/mapObjects/viridianforestentrance.asm"
+
+INCLUDE "data/mapHeaders/undergroundpathentranceroute5.asm"
+INCLUDE "scripts/undergroundpathentranceroute5.asm"
+INCLUDE "data/mapObjects/undergroundpathentranceroute5.asm"
+
+INCLUDE "data/mapHeaders/undergroundpathentranceroute6.asm"
+INCLUDE "scripts/undergroundpathentranceroute6.asm"
+INCLUDE "data/mapObjects/undergroundpathentranceroute6.asm"
+
+INCLUDE "data/mapHeaders/undergroundpathentranceroute7.asm"
+INCLUDE "scripts/undergroundpathentranceroute7.asm"
+INCLUDE "data/mapObjects/undergroundpathentranceroute7.asm"
+
+INCLUDE "data/mapHeaders/undergroundpathentranceroute7copy.asm"
+INCLUDE "scripts/undergroundpathentranceroute7copy.asm"
+INCLUDE "data/mapObjects/undergroundpathentranceroute7copy.asm"
+
+INCLUDE "data/mapHeaders/silphco9.asm"
+INCLUDE "scripts/silphco9.asm"
+INCLUDE "data/mapObjects/silphco9.asm"
+SilphCo9Blocks: INCBIN "maps/silphco9.blk"
+
+INCLUDE "data/mapHeaders/victoryroad1.asm"
+INCLUDE "scripts/victoryroad1.asm"
+INCLUDE "data/mapObjects/victoryroad1.asm"
+VictoryRoad1Blocks: INCBIN "maps/victoryroad1.blk"
+
+INCLUDE "engine/predefs17_2.asm"
+
+INCLUDE "engine/hidden_object_functions17.asm"
+
+
+SECTION "bank18",ROMX,BANK[$18]
+
+ViridianForestBlocks: INCBIN "maps/viridianforest.blk"
+UndergroundPathNSBlocks: INCBIN "maps/undergroundpathns.blk"
+UndergroundPathWEBlocks: INCBIN "maps/undergroundpathwe.blk"
+
+ INCBIN "maps/unusedblocks60258.blk"
+
+SSAnne10Blocks:
+SSAnne9Blocks: INCBIN "maps/ssanne9.blk"
+
+INCLUDE "data/mapHeaders/pokemontower1.asm"
+INCLUDE "scripts/pokemontower1.asm"
+INCLUDE "data/mapObjects/pokemontower1.asm"
+PokemonTower1Blocks: INCBIN "maps/pokemontower1.blk"
+
+INCLUDE "data/mapHeaders/pokemontower2.asm"
+INCLUDE "scripts/pokemontower2.asm"
+INCLUDE "data/mapObjects/pokemontower2.asm"
+PokemonTower2Blocks: INCBIN "maps/pokemontower2.blk"
+
+INCLUDE "data/mapHeaders/pokemontower3.asm"
+INCLUDE "scripts/pokemontower3.asm"
+INCLUDE "data/mapObjects/pokemontower3.asm"
+PokemonTower3Blocks: INCBIN "maps/pokemontower3.blk"
+
+INCLUDE "data/mapHeaders/pokemontower4.asm"
+INCLUDE "scripts/pokemontower4.asm"
+INCLUDE "data/mapObjects/pokemontower4.asm"
+PokemonTower4Blocks: INCBIN "maps/pokemontower4.blk"
+
+INCLUDE "data/mapHeaders/pokemontower5.asm"
+INCLUDE "scripts/pokemontower5.asm"
+INCLUDE "data/mapObjects/pokemontower5.asm"
+PokemonTower5Blocks: INCBIN "maps/pokemontower5.blk"
+
+INCLUDE "data/mapHeaders/pokemontower6.asm"
+INCLUDE "scripts/pokemontower6.asm"
+INCLUDE "data/mapObjects/pokemontower6.asm"
+PokemonTower6Blocks: INCBIN "maps/pokemontower6.blk"
+
+ INCBIN "maps/unusedblocks60cef.blk"
+
+INCLUDE "data/mapHeaders/pokemontower7.asm"
+INCLUDE "scripts/pokemontower7.asm"
+INCLUDE "data/mapObjects/pokemontower7.asm"
+PokemonTower7Blocks: INCBIN "maps/pokemontower7.blk"
+
+INCLUDE "data/mapHeaders/celadonmart1.asm"
+INCLUDE "scripts/celadonmart1.asm"
+INCLUDE "data/mapObjects/celadonmart1.asm"
+CeladonMart1Blocks: INCBIN "maps/celadonmart1.blk"
+
+INCLUDE "engine/overworld/cinnabar_lab.asm"
+
+INCLUDE "data/mapHeaders/viridianforest.asm"
+INCLUDE "scripts/viridianforest.asm"
+INCLUDE "data/mapObjects/viridianforest.asm"
+
+INCLUDE "data/mapHeaders/ssanne1.asm"
+INCLUDE "scripts/ssanne1.asm"
+INCLUDE "data/mapObjects/ssanne1.asm"
+SSAnne1Blocks: INCBIN "maps/ssanne1.blk"
+
+INCLUDE "data/mapHeaders/ssanne2.asm"
+INCLUDE "scripts/ssanne2.asm"
+INCLUDE "data/mapObjects/ssanne2.asm"
+SSAnne2Blocks: INCBIN "maps/ssanne2.blk"
+
+INCLUDE "data/mapHeaders/ssanne4.asm"
+INCLUDE "scripts/ssanne4.asm"
+INCLUDE "data/mapObjects/ssanne4.asm"
+SSAnne4Blocks: INCBIN "maps/ssanne4.blk"
+
+INCLUDE "data/mapHeaders/ssanne5.asm"
+INCLUDE "scripts/ssanne5.asm"
+INCLUDE "data/mapObjects/ssanne5.asm"
+SSAnne5Blocks: INCBIN "maps/ssanne5.blk"
+
+INCLUDE "data/mapHeaders/ssanne6.asm"
+INCLUDE "scripts/ssanne6.asm"
+INCLUDE "data/mapObjects/ssanne6.asm"
+SSAnne6Blocks: INCBIN "maps/ssanne6.blk"
+
+INCLUDE "data/mapHeaders/ssanne7.asm"
+INCLUDE "scripts/ssanne7.asm"
+INCLUDE "data/mapObjects/ssanne7.asm"
+SSAnne7Blocks: INCBIN "maps/ssanne7.blk"
+
+INCLUDE "data/mapHeaders/ssanne8.asm"
+INCLUDE "scripts/ssanne8.asm"
+INCLUDE "data/mapObjects/ssanne8.asm"
+SSAnne8Blocks: INCBIN "maps/ssanne8.blk"
+
+INCLUDE "data/mapHeaders/ssanne9.asm"
+INCLUDE "scripts/ssanne9.asm"
+INCLUDE "data/mapObjects/ssanne9.asm"
+
+INCLUDE "data/mapHeaders/ssanne10.asm"
+INCLUDE "scripts/ssanne10.asm"
+INCLUDE "data/mapObjects/ssanne10.asm"
+
+INCLUDE "data/mapHeaders/undergroundpathns.asm"
+INCLUDE "scripts/undergroundpathns.asm"
+INCLUDE "data/mapObjects/undergroundpathns.asm"
+
+INCLUDE "data/mapHeaders/undergroundpathwe.asm"
+INCLUDE "scripts/undergroundpathwe.asm"
+INCLUDE "data/mapObjects/undergroundpathwe.asm"
+
+INCLUDE "data/mapHeaders/diglettscave.asm"
+INCLUDE "scripts/diglettscave.asm"
+INCLUDE "data/mapObjects/diglettscave.asm"
+DiglettsCaveBlocks: INCBIN "maps/diglettscave.blk"
+
+INCLUDE "data/mapHeaders/silphco11.asm"
+INCLUDE "scripts/silphco11.asm"
+INCLUDE "data/mapObjects/silphco11.asm"
+SilphCo11Blocks: INCBIN "maps/silphco11.blk"
+
+INCLUDE "engine/hidden_object_functions18.asm"
+
+
+SECTION "bank19",ROMX,BANK[$19]
+
+Overworld_GFX: INCBIN "gfx/tilesets/overworld.t2.2bpp"
+Overworld_Block: INCBIN "gfx/blocksets/overworld.bst"
+
+RedsHouse1_GFX:
+RedsHouse2_GFX: INCBIN "gfx/tilesets/reds_house.t7.2bpp"
+RedsHouse1_Block:
+RedsHouse2_Block: INCBIN "gfx/blocksets/reds_house.bst"
+
+House_GFX: INCBIN "gfx/tilesets/house.t2.2bpp"
+House_Block: INCBIN "gfx/blocksets/house.bst"
+Mansion_GFX: INCBIN "gfx/tilesets/mansion.t2.2bpp"
+Mansion_Block: INCBIN "gfx/blocksets/mansion.bst"
+ShipPort_GFX: INCBIN "gfx/tilesets/ship_port.t2.2bpp"
+ShipPort_Block: INCBIN "gfx/blocksets/ship_port.bst"
+Interior_GFX: INCBIN "gfx/tilesets/interior.t1.2bpp"
+Interior_Block: INCBIN "gfx/blocksets/interior.bst"
+Plateau_GFX: INCBIN "gfx/tilesets/plateau.t10.2bpp"
+Plateau_Block: INCBIN "gfx/blocksets/plateau.bst"
+
+
+SECTION "bank1A",ROMX,BANK[$1A]
+
+INCLUDE "engine/battle/decrement_pp.asm"
+
+Version_GFX:
+IF DEF(_RED)
+ INCBIN "gfx/red/redgreenversion.1bpp" ; 10 tiles
+ENDC
+IF DEF(_BLUE)
+ INCBIN "gfx/blue/blueversion.1bpp" ; 8 tiles
+ENDC
+
+Dojo_GFX:
+Gym_GFX: INCBIN "gfx/tilesets/gym.2bpp"
+Dojo_Block:
+Gym_Block: INCBIN "gfx/blocksets/gym.bst"
+
+Mart_GFX:
+Pokecenter_GFX: INCBIN "gfx/tilesets/pokecenter.2bpp"
+Mart_Block:
+Pokecenter_Block: INCBIN "gfx/blocksets/pokecenter.bst"
+
+ForestGate_GFX:
+Museum_GFX:
+Gate_GFX: INCBIN "gfx/tilesets/gate.t1.2bpp"
+ForestGate_Block:
+Museum_Block:
+Gate_Block: INCBIN "gfx/blocksets/gate.bst"
+
+Forest_GFX: INCBIN "gfx/tilesets/forest.2bpp"
+Forest_Block: INCBIN "gfx/blocksets/forest.bst"
+Facility_GFX: INCBIN "gfx/tilesets/facility.2bpp"
+Facility_Block: INCBIN "gfx/blocksets/facility.bst"
+
+
+SECTION "bank1B",ROMX,BANK[$1B]
+
+Cemetery_GFX: INCBIN "gfx/tilesets/cemetery.t4.2bpp"
+Cemetery_Block: INCBIN "gfx/blocksets/cemetery.bst"
+Cavern_GFX: INCBIN "gfx/tilesets/cavern.t14.2bpp"
+Cavern_Block: INCBIN "gfx/blocksets/cavern.bst"
+Lobby_GFX: INCBIN "gfx/tilesets/lobby.t2.2bpp"
+Lobby_Block: INCBIN "gfx/blocksets/lobby.bst"
+Ship_GFX: INCBIN "gfx/tilesets/ship.t6.2bpp"
+Ship_Block: INCBIN "gfx/blocksets/ship.bst"
+Lab_GFX: INCBIN "gfx/tilesets/lab.t4.2bpp"
+Lab_Block: INCBIN "gfx/blocksets/lab.bst"
+Club_GFX: INCBIN "gfx/tilesets/club.t5.2bpp"
+Club_Block: INCBIN "gfx/blocksets/club.bst"
+Underground_GFX: INCBIN "gfx/tilesets/underground.t7.2bpp"
+Underground_Block: INCBIN "gfx/blocksets/underground.bst"
+
+
+SECTION "bank1C",ROMX,BANK[$1C]
+
+INCLUDE "engine/gamefreak.asm"
+INCLUDE "engine/hall_of_fame.asm"
+INCLUDE "engine/overworld/healing_machine.asm"
+INCLUDE "engine/overworld/player_animations.asm"
+INCLUDE "engine/battle/ghost_marowak_anim.asm"
+INCLUDE "engine/battle/battle_transitions.asm"
+INCLUDE "engine/town_map.asm"
+INCLUDE "engine/mon_party_sprites.asm"
+INCLUDE "engine/in_game_trades.asm"
+INCLUDE "engine/palettes.asm"
+INCLUDE "engine/save.asm"
+
+
+SECTION "bank1D",ROMX,BANK[$1D]
+
+CopycatsHouse1FBlocks: INCBIN "maps/copycatshouse1f.blk"
+
+CinnabarMartBlocks:
+PewterMartBlocks: INCBIN "maps/pewtermart.blk"
+
+FuchsiaHouse1Blocks: INCBIN "maps/fuchsiahouse1.blk"
+
+CinnabarPokecenterBlocks:
+FuchsiaPokecenterBlocks: INCBIN "maps/fuchsiapokecenter.blk"
+
+CeruleanHouse2Blocks: INCBIN "maps/ceruleanhouse2.blk"
+
+INCLUDE "engine/HoF_room_pc.asm"
+
+INCLUDE "engine/status_ailments.asm"
+
+INCLUDE "engine/items/itemfinder.asm"
+
+INCLUDE "scripts/ceruleancity2.asm"
+
+INCLUDE "data/mapHeaders/viridiangym.asm"
+INCLUDE "scripts/viridiangym.asm"
+INCLUDE "data/mapObjects/viridiangym.asm"
+ViridianGymBlocks: INCBIN "maps/viridiangym.blk"
+
+INCLUDE "data/mapHeaders/pewtermart.asm"
+INCLUDE "scripts/pewtermart.asm"
+INCLUDE "data/mapObjects/pewtermart.asm"
+
+INCLUDE "data/mapHeaders/unknowndungeon1.asm"
+INCLUDE "scripts/unknowndungeon1.asm"
+INCLUDE "data/mapObjects/unknowndungeon1.asm"
+UnknownDungeon1Blocks: INCBIN "maps/unknowndungeon1.blk"
+
+INCLUDE "data/mapHeaders/ceruleanhouse2.asm"
+INCLUDE "scripts/ceruleanhouse2.asm"
+INCLUDE "data/mapObjects/ceruleanhouse2.asm"
+
+INCLUDE "engine/menu/vending_machine.asm"
+
+INCLUDE "data/mapHeaders/fuchsiahouse1.asm"
+INCLUDE "scripts/fuchsiahouse1.asm"
+INCLUDE "data/mapObjects/fuchsiahouse1.asm"
+
+INCLUDE "data/mapHeaders/fuchsiapokecenter.asm"
+INCLUDE "scripts/fuchsiapokecenter.asm"
+INCLUDE "data/mapObjects/fuchsiapokecenter.asm"
+
+INCLUDE "data/mapHeaders/fuchsiahouse2.asm"
+INCLUDE "scripts/fuchsiahouse2.asm"
+INCLUDE "data/mapObjects/fuchsiahouse2.asm"
+FuchsiaHouse2Blocks: INCBIN "maps/fuchsiahouse2.blk"
+
+INCLUDE "data/mapHeaders/safarizoneentrance.asm"
+INCLUDE "scripts/safarizoneentrance.asm"
+INCLUDE "data/mapObjects/safarizoneentrance.asm"
+SafariZoneEntranceBlocks: INCBIN "maps/safarizoneentrance.blk"
+
+INCLUDE "data/mapHeaders/fuchsiagym.asm"
+INCLUDE "scripts/fuchsiagym.asm"
+INCLUDE "data/mapObjects/fuchsiagym.asm"
+FuchsiaGymBlocks: INCBIN "maps/fuchsiagym.blk"
+
+INCLUDE "data/mapHeaders/fuchsiameetingroom.asm"
+INCLUDE "scripts/fuchsiameetingroom.asm"
+INCLUDE "data/mapObjects/fuchsiameetingroom.asm"
+FuchsiaMeetingRoomBlocks: INCBIN "maps/fuchsiameetingroom.blk"
+
+INCLUDE "data/mapHeaders/cinnabargym.asm"
+INCLUDE "scripts/cinnabargym.asm"
+INCLUDE "data/mapObjects/cinnabargym.asm"
+CinnabarGymBlocks: INCBIN "maps/cinnabargym.blk"
+
+INCLUDE "data/mapHeaders/lab1.asm"
+INCLUDE "scripts/lab1.asm"
+INCLUDE "data/mapObjects/lab1.asm"
+Lab1Blocks: INCBIN "maps/lab1.blk"
+
+INCLUDE "data/mapHeaders/lab2.asm"
+INCLUDE "scripts/lab2.asm"
+INCLUDE "data/mapObjects/lab2.asm"
+Lab2Blocks: INCBIN "maps/lab2.blk"
+
+INCLUDE "data/mapHeaders/lab3.asm"
+INCLUDE "scripts/lab3.asm"
+INCLUDE "data/mapObjects/lab3.asm"
+Lab3Blocks: INCBIN "maps/lab3.blk"
+
+INCLUDE "data/mapHeaders/lab4.asm"
+INCLUDE "scripts/lab4.asm"
+INCLUDE "data/mapObjects/lab4.asm"
+Lab4Blocks: INCBIN "maps/lab4.blk"
+
+INCLUDE "data/mapHeaders/cinnabarpokecenter.asm"
+INCLUDE "scripts/cinnabarpokecenter.asm"
+INCLUDE "data/mapObjects/cinnabarpokecenter.asm"
+
+INCLUDE "data/mapHeaders/cinnabarmart.asm"
+INCLUDE "scripts/cinnabarmart.asm"
+INCLUDE "data/mapObjects/cinnabarmart.asm"
+
+INCLUDE "data/mapHeaders/copycatshouse1f.asm"
+INCLUDE "scripts/copycatshouse1f.asm"
+INCLUDE "data/mapObjects/copycatshouse1f.asm"
+
+INCLUDE "data/mapHeaders/gary.asm"
+INCLUDE "scripts/gary.asm"
+INCLUDE "data/mapObjects/gary.asm"
+GaryBlocks: INCBIN "maps/gary.blk"
+
+INCLUDE "data/mapHeaders/lorelei.asm"
+INCLUDE "scripts/lorelei.asm"
+INCLUDE "data/mapObjects/lorelei.asm"
+LoreleiBlocks: INCBIN "maps/lorelei.blk"
+
+INCLUDE "data/mapHeaders/bruno.asm"
+INCLUDE "scripts/bruno.asm"
+INCLUDE "data/mapObjects/bruno.asm"
+BrunoBlocks: INCBIN "maps/bruno.blk"
+
+INCLUDE "data/mapHeaders/agatha.asm"
+INCLUDE "scripts/agatha.asm"
+INCLUDE "data/mapObjects/agatha.asm"
+AgathaBlocks: INCBIN "maps/agatha.blk"
+
+INCLUDE "engine/menu/league_pc.asm"
+
+INCLUDE "engine/overworld/hidden_items.asm"
+
+
+SECTION "bank1E",ROMX,BANK[$1E]
+
+INCLUDE "engine/battle/animations.asm"
+
+INCLUDE "engine/overworld/cut2.asm"
+
+INCLUDE "engine/overworld/ssanne.asm"
+
+RedFishingTilesFront: INCBIN "gfx/red_fishing_tile_front.2bpp"
+RedFishingTilesBack: INCBIN "gfx/red_fishing_tile_back.2bpp"
+RedFishingTilesSide: INCBIN "gfx/red_fishing_tile_side.2bpp"
+RedFishingRodTiles: INCBIN "gfx/red_fishingrod_tiles.2bpp"
+
+INCLUDE "data/animations.asm"
+
+INCLUDE "engine/evolution.asm"
+
+INCLUDE "engine/overworld/elevator.asm"
+
+INCLUDE "engine/items/tm_prices.asm"
+
+IF DEF(_OPTION_BEACH_HOUSE)
+SECTION "bank3C",ROMX[$4314],BANK[$3C]
+
+BeachHouse_GFX:
+ INCBIN "gfx/tilesets/beachhouse.2bpp"
+
+BeachHouse_Block:
+ INCBIN "gfx/blocksets/beachhouse.bst"
+ENDC
+
+SECTION "bank3d",ROMX,BANK[$3D]
+
+INCLUDE "engine/random.asm"
@@ -1,2297 +1,2305 @@ - -INCLUDE "constants.asm" - -flag_array: MACRO - ds ((\1) + 7) / 8 -ENDM - -box_struct_length EQU 25 + NUM_MOVES * 2 -box_struct: MACRO -\1Species:: db -\1HP:: dw -\1BoxLevel:: db -\1Status:: db -\1Type:: -\1Type1:: db -\1Type2:: db -\1CatchRate:: db -\1Moves:: ds NUM_MOVES -\1OTID:: dw -\1Exp:: ds 3 -\1HPExp:: dw -\1AttackExp:: dw -\1DefenseExp:: dw -\1SpeedExp:: dw -\1SpecialExp:: dw -\1DVs:: ds 2 -\1PP:: ds NUM_MOVES -ENDM - -party_struct: MACRO - box_struct \1 -\1Level:: db -\1Stats:: -\1MaxHP:: dw -\1Attack:: dw -\1Defense:: dw -\1Speed:: dw -\1Special:: dw -ENDM - -battle_struct: MACRO -\1Species:: db -\1HP:: dw -\1BoxLevel:: db -\1Status:: db -\1Type:: -\1Type1:: db -\1Type2:: db -\1CatchRate:: db -\1Moves:: ds NUM_MOVES -\1DVs:: ds 2 -\1Level:: db -\1MaxHP:: dw -\1Attack:: dw -\1Defense:: dw -\1Speed:: dw -\1Special:: dw -\1PP:: ds NUM_MOVES -ENDM - - -SECTION "WRAM Bank 0", WRAM0 - -wc000:: ds 1 -wc001:: ds 1 -wc002:: ds 1 -wc003:: ds 1 -wc004:: ds 1 -wc005:: ds 1 -wc006:: ds 8 -wc00e:: ds 4 -wc012:: ds 4 -wc016:: ds 16 -wc026:: ds 1 -wc027:: ds 1 -wc028:: ds 2 -wc02a:: ds 1 -wc02b:: ds 1 -wc02c:: ds 1 -wc02d:: ds 1 -wc02e:: ds 8 -wc036:: ds 8 -wc03e:: ds 8 -wc046:: ds 8 -wc04e:: ds 8 -wc056:: ds 8 -wc05e:: ds 8 -wc066:: ds 8 -wc06e:: ds 8 -wc076:: ds 8 -wc07e:: ds 8 -wc086:: ds 8 -wc08e:: ds 8 -wc096:: ds 8 -wc09e:: ds 8 -wc0a6:: ds 8 -wc0ae:: ds 8 -wc0b6:: ds 8 -wc0be:: ds 8 -wc0c6:: ds 8 -wc0ce:: ds 1 -wc0cf:: ds 1 -wc0d0:: ds 1 -wc0d1:: ds 1 -wc0d2:: ds 1 -wc0d3:: ds 1 -wc0d4:: ds 1 -wc0d5:: ds 1 -wc0d6:: ds 8 -wc0de:: ds 8 -wc0e6:: ds 1 -wc0e7:: ds 1 -wc0e8:: ds 1 -wc0e9:: ds 1 -wc0ea:: ds 1 -wc0eb:: ds 1 -wc0ec:: ds 1 -wc0ed:: ds 1 -wc0ee:: ds 1 -wc0ef:: ds 1 -wc0f0:: ds 1 -wc0f1:: ds 1 -wc0f2:: ds 14 - - -SECTION "Sprite State Data", WRAM0[$c100] - -wSpriteStateData1:: ; c100 -; data for all sprites on the current map -; holds info for 16 sprites with $10 bytes each -; player sprite is always sprite 0 -; C1x0: picture ID (fixed, loaded at map init) -; C1x1: movement status (0: uninitialized, 1: ready, 2: delayed, 3: moving) -; C1x2: sprite image index (changed on update, $ff if off screen, includes facing direction, progress in walking animation and a sprite-specific offset) -; C1x3: Y screen position delta (-1,0 or 1; added to c1x4 on each walking animation update) -; C1x4: Y screen position (in pixels, always 4 pixels above grid which makes sprites appear to be in the center of a tile) -; C1x5: X screen position delta (-1,0 or 1; added to c1x6 on each walking animation update) -; C1x6: X screen position (in pixels, snaps to grid if not currently walking) -; C1x7: intra-animation-frame counter (counting upwards to 4 until c1x8 is incremented) -; C1x8: animation frame counter (increased every 4 updates, hold four states (totalling to 16 walking frames) -; C1x9: facing direction (0: down, 4: up, 8: left, $c: right) -; C1xA -; C1xB -; C1xC -; C1xD -; C1xE -; C1xF - ds $10 * $10 - - -SECTION "Sprite State Data 2", WRAM0[$c200] - -wSpriteStateData2:: ; c200 -; more data for all sprites on the current map -; holds info for 16 sprites with $10 bytes each -; player sprite is always sprite 0 -; C2x0: walk animation counter (counting from $10 backwards when moving) -; C2x1: -; C2x2: Y displacement (initialized at 8, supposed to keep moving sprites from moving too far, but bugged) -; C2x3: X displacement (initialized at 8, supposed to keep moving sprites from moving too far, but bugged) -; C2x4: Y position (in 2x2 tile grid steps, topmost 2x2 tile has value 4) -; C2x5: X position (in 2x2 tile grid steps, leftmost 2x2 tile has value 4) -; C2x6: movement byte 1 (determines whether a sprite can move, $ff:not moving, $fe:random movements, others unknown) -; C2x7: (?) (set to $80 when in grass, else $0; may be used to draw grass above the sprite) -; C2x8: delay until next movement (counted downwards, status (c1x1) is set to ready if reached 0) -; C2x9 -; C2xA -; C2xB -; C2xC -; C2xD -; C2xE: sprite image base offset (in video ram, player always has value 1, used to compute c1x2) -; C2xF - ds $10 * $10 - - -SECTION "OAM Buffer", WRAM0[$c300] - -wOAMBuffer:: ; c300 -; buffer for OAM data. Copied to OAM by DMA - ds 4 * 40 - -wTileMap:: ; c3a0 -; buffer for tiles that are visible on screen (20 columns by 18 rows) - ds 20 * 18 - -wSerialPartyMonsPatchList:: ; c508 -; list of indexes to patch with SERIAL_NO_DATA_BYTE after transfer - -wTileMapBackup:: ; c508 -; buffer for temporarily saving and restoring current screen's tiles -; (e.g. if menus are drawn on top) -; ds 20 * 18 - - ds 200 - -wSerialEnemyMonsPatchList:: ; c5d0 -; list of indexes to patch with SERIAL_NO_DATA_BYTE after transfer - ds 200 - - ds 80 - -wTempPic:: -wOverworldMap:: ; c6e8 - ds 1300 - -wScreenEdgeTiles:: ; cbfc -; the tiles of the row or column to be redrawn by RedrawExposedScreenEdge - ds 20 * 2 - -; coordinates of the position of the cursor for the top menu item (id 0) -wTopMenuItemY:: ; cc24 - ds 1 -wTopMenuItemX:: ; cc25 - ds 1 - -wCurrentMenuItem:: ; cc26 -; the id of the currently selected menu item -; the top item has id 0, the one below that has id 1, etc. -; note that the "top item" means the top item currently visible on the screen -; add this value to [wListScrollOffset] to get the item's position within the list - ds 1 - -wTileBehindCursor:: ; cc27 -; the tile that was behind the menu cursor's current location - ds 1 - -wMaxMenuItem:: ; cc28 -; id of the bottom menu item - ds 1 - -wMenuWatchedKeys:: ; cc29 -; bit mask of keys that the menu will respond to - ds 1 - -wLastMenuItem:: ; cc2a -; id of previously selected menu item - ds 1 - -wcc2b:: ds 1 -wcc2c:: ds 1 -wcc2d:: ds 1 - -wPlayerMoveListIndex:: ; cc2e - ds 1 - -wPlayerMonNumber:: ; cc2f - ds 1 - -wMenuCursorLocation:: ; cc30 -; the address of the menu cursor's current location within wTileMap - ds 2 - - ds 2 - -wMenuJoypadPollCount:: ; cc34 -; how many times should HandleMenuInput poll the joypad state before it returns? - ds 1 - -wMenuItemToSwap:: ; cc35 -; id of menu item selected for swapping (counts from 1) (0 means that no menu item has been selected for swapping) - ds 1 - -wListScrollOffset:: ; cc36 -; offset of the current top menu item from the beginning of the list -; keeps track of what section of the list is on screen - ds 1 - -wcc37:: ds 1 - -wTradeCenterPointerTableIndex:: ; cc38 - ds 1 - - ds 1 - -wcc3a:: ds 1 -wcc3b:: ds 1 - -wDoNotWaitForButtonPressAfterDisplayingText:: ; cc3c -; if non-zero, skip waiting for a button press after displaying text in DisplayTextID - ds 1 - -wSerialSyncAndExchangeNybbleReceiveData:: ; cc3d -; the final received nybble is stored here by Serial_SyncAndExchangeNybble - -wSerialExchangeNybbleTempReceiveData:: ; cc3d -; temporary nybble used by Serial_ExchangeNybble - -wLinkMenuSelectionReceiveBuffer:: ; cc3d -; two byte buffer -; the received menu selection is stored twice - -wcc3d:: ds 1 - -wSerialExchangeNybbleReceiveData:: ; cc3e -; the final received nybble is stored here by Serial_ExchangeNybble - ds 1 - - ds 3 - -wSerialExchangeNybbleSendData:: ; cc42 -; this nybble is sent when using Serial_SyncAndExchangeNybble or Serial_ExchangeNybble - -wLinkMenuSelectionSendBuffer:: ; cc42 -; two byte buffer -; the menu selection byte is stored twice before sending - - ds 5 - -wLinkTimeoutCounter:: ; cc47 -; 1 byte - -wUnknownSerialCounter:: ; cc47 -; 2 bytes - -wcc47:: ds 1 -wcc48:: ds 1 - -wWhichTradeMonSelectionMenu:: ; cc49 -; $00 = player mons -; $01 = enemy mons - -wcc49:: ds 1 - -wMenuWrappingEnabled:: ; cc4a -; set to 1 if you can go from the bottom to the top or top to bottom of a menu -; set to 0 if you can't go past the top or bottom of the menu - ds 1 - -wcc4b:: ds 2 -wcc4d:: ds 1 - -wPredefID:: ; cc4e - ds 1 -wPredefRegisters:: ; cc4f - ds 6 - -wTrainerHeaderFlagBit:: ; cc55 - ds 1 - - ds 1 - -wNPCMovementScriptPointerTableNum:: ; cc57 -; which NPC movement script pointer is being used -; 0 if an NPC movement script is not running - ds 1 - -wNPCMovementScriptBank:: ; cc58 -; ROM bank of current NPC movement script - ds 1 - - ds 2 - -wHallOfFame:: ; cc5b -wBoostExpByExpAll:: ; cc5b -wAnimationType:: ; cc5b -; values between 0-6. Shake screen horizontally, shake screen vertically, blink Pokemon... - -wcc5b:: ds 1 -wcc5c:: ds 1 -wcc5d:: ds 1 -wcc5e:: ds 13 - -wcc6b:: ds 14 -wcc79:: ds 30 - -wNPCMovementDirections2:: ; cc97 - -wSwitchPartyMonTempBuffer:: ; cc97 -; temporary buffer when swapping party mon data - ds 10 - -wcca1:: ds 49 - -wRLEByteCount:: ; ccd2 - ds 1 - -wSimulatedJoypadStatesEnd:: ; ccd3 -; this is the end of the joypad states -; the list starts above this address and extends downwards in memory until here -; overloaded with below labels - -wccd3:: ds 1 -wccd4:: ds 1 - -; if [ccd5] != 1, the second AI layer is not applied -wAILayer2Encouragement:: ; ccd5 - ds 1 - ds 1 - -; current HP of player and enemy substitutes -wPlayerSubstituteHP:: ; ccd7 - ds 1 -wEnemySubstituteHP:: ; ccd8 - ds 1 - -wccd9:: ds 2 - -wMoveMenuType:: ; ccdb -; 0=regular, 1=mimic, 2=above message box (relearn, heal pp..) - ds 1 - -wPlayerSelectedMove:: ; ccdc - ds 1 -wEnemySelectedMove:: ; ccdd - ds 1 - -wLinkBattleRandomNumberListIndex:: ; ccde - ds 1 - -wAICount:: ; ccdf -; number of times remaining that AI action can occur - ds 1 - - ds 2 - -wEnemyMoveListIndex:: ; cce2 - ds 1 - -wcce3:: ds 1 -wcce4:: ds 1 - -wTotalPayDayMoney:: ; cce5 -; total amount of money made using Pay Day during the current battle - ds 3 - -wSafariEscapeFactor:: ; cce8 - ds 1 -wSafariBaitFactor:: ; cce9 - ds 1; - - ds 1 - -wcceb:: ds 1 -wccec:: ds 1 - -wMonIsDisobedient:: ds 1 ; cced - -wPlayerDisabledMoveNumber:: ds 1 ; ccee -wEnemyDisabledMoveNumber:: ds 1 ; ccef - -wccf0:: ds 1 - -wPlayerUsedMove:: ds 1 ; ccf1 -wEnemyUsedMove:: ds 1 ; ccf2 - -wccf3:: ds 1 - -wMoveDidntMiss:: ds 1 ; ccf4 - -wPartyFoughtCurrentEnemyFlags:: ; ccf5 -; flags that indicate which party members have fought the current enemy mon - flag_array 6 - -wccf6:: ds 1 -wccf7:: ds 14 - -wUnknownSlotVar:: ; cd05 - -wEnemyNumHits:: ; cd05 -; number of hits by enemy in attacks like Double Slap, etc. - -wEnemyBideAccumulatedDamage:: ; cd05 -; the amount of damage accumulated by the enemy while biding (2 bytes) - -ds 10 - -wInGameTradeGiveMonSpecies:: ; cd0f - -wPlayerMonUnmodifiedLevel:: ; cd0f - ds 1 - -wInGameTradeTextPointerTablePointer:: ; cd10 - -wPlayerMonUnmodifiedMaxHP:: ; cd10 - ds 2 - -wInGameTradeTextPointerTableIndex:: ; cd12 - -wPlayerMonUnmodifiedAttack:: ; cd12 - ds 1 -wInGameTradeGiveMonName:: ; cd13 - ds 1 -wPlayerMonUnmodifiedDefense:: ; cd14 - ds 2 -wPlayerMonUnmodifiedSpeed:: ; cd16 - ds 2 -wPlayerMonUnmodifiedSpecial:: ; cd18 - ds 2 - -; stat modifiers for the player's current pokemon -; value can range from 1 - 13 ($1 to $D) -; 7 is normal - -wPlayerMonStatMods:: -wPlayerMonAttackMod:: ; cd1a - ds 1 -wPlayerMonDefenseMod:: ; cd1b - ds 1 -wPlayerMonSpeedMod:: ; cd1c - ds 1 -wPlayerMonSpecialMod:: ; cd1d - ds 1 - -wInGameTradeReceiveMonName:: ; cd1e - -wPlayerMonAccuracyMod:: ; cd1e - ds 1 -wPlayerMonEvasionMod:: ; cd1f - ds 1 - - ds 3 - -wEnemyMonUnmodifiedLevel:: ; cd23 - ds 1 -wEnemyMonUnmodifiedMaxHP:: ; cd24 - ds 2 -wEnemyMonUnmodifiedAttack:: ; cd26 - ds 2 -wEnemyMonUnmodifiedDefense:: ; cd28 - ds 1 - -wInGameTradeMonNick:: ; cd29 - ds 1 - -wEnemyMonUnmodifiedSpeed:: ; cd2a - ds 2 -wEnemyMonUnmodifiedSpecial:: ; cd2c - ds 1 - -wEngagedTrainerClass:: ; cd2d - ds 1 -wEngagedTrainerSet:: ; cd2e -; ds 1 - -; stat modifiers for the enemy's current pokemon -; value can range from 1 - 13 ($1 to $D) -; 7 is normal - -wEnemyMonStatMods:: -wEnemyMonAttackMod:: ; cd2e - ds 1 -wEnemyMonDefenseMod:: ; cd2f - ds 1 -wEnemyMonSpeedMod:: ; cd30 - ds 1 -wEnemyMonSpecialMod:: ; cd31 - ds 1 -wEnemyMonAccuracyMod:: ; cd32 - ds 1 -wEnemyMonEvasionMod:: ; cd33 - ds 1 - -wInGameTradeReceiveMonSpecies:: - ds 1 - - ds 2 - -wNPCMovementDirections2Index:: ; cd37 - -wcd37:: ds 1 - -wSimulatedJoypadStatesIndex:: ; cd38 -; the next simulated joypad state is at wSimulatedJoypadStatesEnd plus this value minus 1 -; 0 if the joypad state is not being simulated - ds 1 - -wWastedByteCD39:: ; cd39 -; written to but nothing ever reads it - ds 1 - -wWastedByteCD3A:: ; cd3a -; written to but nothing ever reads it - ds 1 - -wOverrideSimulatedJoypadStatesMask:: ; cd3b -; mask indicating which real button presses can override simulated ones -; XXX is it ever not 0? - ds 1 - - ds 1 - -wTradedPlayerMonSpecies:: ; cd3d - -wTradingWhichPlayerMon:: ; cd3d - -wChangeBoxSavedMapTextPointer:: ; cd3d - -wFlyAnimUsingCoordList:: ; cd3d - -wPlayerSpinInPlaceAnimFrameDelay:: ; cd3d - -wPlayerSpinWhileMovingUpOrDownAnimDeltaY:: ; cd3d - -wHiddenObjectFunctionArgument:: ; cd3d - -wSubtrahend:: ; cd3d -; subtract (BCD) wSubtrahend, wSubtrahend+1, wSubtrahend+2 - -wWhichTrade:: ; cd3d -; which entry from TradeMons to select - -wTrainerSpriteOffset:: ; cd3d - ds 1 - -wTradedEnemyMonSpecies:: ; cd3e - -wTradingWhichEnemyMon:: ; cd3e - -wFlyAnimCounter:: ; cd3e - -wPlayerSpinInPlaceAnimFrameDelayDelta:: ; cd3e - -wPlayerSpinWhileMovingUpOrDownAnimMaxY:: ; cd3e - -wHiddenObjectFunctionRomBank:: ; cd3e - -wTrainerEngageDistance:: ; cd3e - ds 1 - -wNameOfPlayerMonToBeTraded:: ; cd3f - -wFlyAnimBirdSpriteImageIndex:: ; cd3f - -wPlayerSpinInPlaceAnimFrameDelayEndValue:: ; cd3f - -wPlayerSpinWhileMovingUpOrDownAnimFrameDelay:: ; cd3f - -wHiddenObjectIndex:: ; cd3f - -wTrainerFacingDirection:: ; cd3f -wcd3f:: - ds 1 - -wPlayerSpinInPlaceAnimSoundID:: ; cd40 - -wHiddenObjectY:: ; cd40 - -wTrainerScreenY:: ; cd40 - ds 1 - -wTradedPlayerMonOT:: ; cd41 - -wHiddenObjectX:: ; cd41 - -wTrainerScreenX:: ; cd41 - ds 1 - -wcd42:: ds 1 -wcd43:: ds 1 -wcd44:: ds 1 -wcd45:: ds 1 -wcd46:: ds 1 -wcd47:: ds 1 -wcd48:: ds 1 -wcd49:: ds 1 -wcd4a:: ds 1 -wcd4b:: ds 1 - -wTradedPlayerMonOTID:: ; cd4c - -wcd4c:: ds 1 -wcd4d:: ds 1 - -wTradedEnemyMonOT:: ; cd4e - -wcd4e:: ds 1 -wcd4f:: ds 1 -wcd50:: ds 9 - -wTradedEnemyMonOTID:: ; cd59 - ds 2 - -wcd5b:: ds 1 -wcd5c:: ds 1 - -wMonPartySpriteSpecies:: ; cd5d - ds 1 - -wLeftGBMonSpecies:: ; cd5e -; in the trade animation, the mon that leaves the left gameboy - ds 1 - -wRightGBMonSpecies:: ; cd5f -; in the trade animation, the mon that leaves the right gameboy - ds 1 - -wFlags_0xcd60:: ; cd60 -; bit 0: is player engaged by trainer (to avoid being engaged by multiple trainers simultaneously) -; bit 1: boulder dust animation (from using Strength) pending -; bit 5: don't play sound when A or B is pressed in menu -; bit 6: tried pushing against boulder once (you need to push twice before it will move) - ds 1 - - ds 9 - -wcd6a:: ds 1 - -wJoyIgnore:: ; cd6b -; Set buttons are ignored. - ds 1 - -wcd6c:: ds 1 -wcd6d:: ds 4 -wcd71:: ds 1 -wcd72:: ds 5 -wcd77:: ds 1 -wcd78:: ds 9 - -wSerialOtherGameboyRandomNumberListBlock:: ; cd81 -; buffer for transferring the random number list generated by the other gameboy - -wTileMapBackup2:: ; cd81 -; second buffer for temporarily saving and restoring current screen's tiles (e.g. if menus are drawn on top) - ds 20 * 18 - -wBuffer:: ; cee9 -; Temporary storage area of 30 bytes. -wHPBarMaxHP:: ; cee9 - ds 2 -wHPBarOldHP:: ; ceeb - ds 2 -wHPBarNewHP:: ; ceed - ds 2 -wHPBarDelta:: ; ceef - ds 1 - -wcef0:: ds 1 -wcef1:: ds 12 - -wHPBarHPDifference:: ; cefd - ds 1 - ds 7 - -wcf05:: ds 1 -wcf06:: ds 1 - -wAnimSoundID:: ; cf07 -; sound ID during battle animations - ds 1 - -wcf08:: ds 1 -wcf09:: ds 1 -wcf0a:: ds 1 -wBattleResult:: ; cf0b -; $00 - win -; $01 - lose -; $02 - draw - ds 1 - -wAutoTextBoxDrawingControl:: ; cf0c -; bit 0: if set, DisplayTextID automatically draws a text box - ds 1 - -wcf0d:: ds 1 -wcf0e:: ds 1 -wcf0f:: ds 1 - -wNPCMovementScriptFunctionNum:: ; cf10 -; which script function within the pointer table indicated by -; wNPCMovementScriptPointerTableNum - ds 1 - -wcf11:: ds 1 - -wPredefParentBank:: ; cf12 - ds 1 - -wSpriteIndex:: ds 1 - -wCurSpriteMovement2:: ; cf14 -; movement byte 2 of current sprite - ds 1 - - ds 2 - -wNPCMovementScriptSpriteOffset:: ; cf17 -; sprite offset of sprite being controlled by NPC movement script - ds 1 - -wcf18:: ds 2 - -wOnSGB:: ; cf1b -; if running on SGB, it's 1, else it's 0 - ds 1 - -wcf1c:: ds 1 -wcf1d:: ds 1 -wcf1e:: ds 1 -wcf1f:: ds 6 -wcf25:: ds 8 -wcf2d:: ds 1 -wcf2e:: ds 2 -wcf30:: ds 7 -wcf37:: ds 20 -wcf4b:: ds 1 -wcf4c:: ds 1 -wGainBoostedExp:: ; cf4d - ds 1 - ds 17 - -wGymCityName:: ; cf5f -wStringBuffer1:: ; cf5f - ds 16 + 1 -wGymLeaderName:: ; cf70 -wStringBuffer2:: ; cf70 - ds 16 + 1 -wStringBuffer3:: ; cf81 - ds 9 + 1 - -wList:: ; cf8b - ds 2 - -wcf8d:: ds 1 -wcf8e:: ds 1 - -wItemPrices:: ; cf8f - ds 2 - -wcf91:: ds 1 - -wWhichPokemon:: ; cf92 -; which pokemon you selected - ds 1 - -wcf93:: ds 1 - -wHPBarType:: ; cf94 -; type of HP bar -; $00 = enemy HUD in battle -; $01 = player HUD in battle / status screen -; $02 = party menu - -wListMenuID:: ; cf94 -; ID used by DisplayListMenuID - ds 1 - -wcf95:: ds 1 -wcf96:: ds 1 -wcf97:: ds 1 - -; LoadMonData copies mon data here -wLoadedMon:: party_struct wLoadedMon ; cf98 - -wFontLoaded:: ; cfc4 -; bit 0: The space in VRAM that is used to store walk animation tile patterns -; for the player and NPCs is in use for font tile patterns. -; This means that NPC movement must be disabled. -; The other bits are unused. - ds 1 - -wWalkCounter:: ; cfc5 -; walk animation counter - ds 1 - -wTileInFrontOfPlayer:: ; cfc6 -; background tile number in front of the player (either 1 or 2 steps ahead) - ds 1 - -wMusicHeaderPointer:: ; cfc7 -; (the current music channel address - $4000) / 3 - ds 1 - -wcfc8:: ds 1 -wcfc9:: ds 1 -wcfca:: ds 1 - -wUpdateSpritesEnabled:: ; cfcb -; $01 enables UpdateSprites; anything else disables it - ds 1 - -W_ENEMYMOVENUM:: ; cfcc - ds 1 -W_ENEMYMOVEEFFECT:: ; cfcd - ds 1 -W_ENEMYMOVEPOWER:: ; cfce - ds 1 -W_ENEMYMOVETYPE:: ; cfcf - ds 1 -W_ENEMYMOVEACCURACY:: ; cfd0 - ds 1 -W_ENEMYMOVEMAXPP:: ; cfd1 - ds 1 -W_PLAYERMOVENUM:: ; cfd2 - ds 1 -W_PLAYERMOVEEFFECT:: ; cfd3 - ds 1 -W_PLAYERMOVEPOWER:: ; cfd4 - ds 1 -W_PLAYERMOVETYPE:: ; cfd5 - ds 1 -W_PLAYERMOVEACCURACY:: ; cfd6 - ds 1 -W_PLAYERMOVEMAXPP:: ; cfd7 - ds 1 - - -wEnemyMonSpecies2:: ; cfd8 - ds 1 -wBattleMonSpecies2:: ; cfd9 - ds 1 - -wEnemyMonNick:: ds 11 ; cfda - -wEnemyMon:: ; cfe5 -; The wEnemyMon struct reaches past 0xcfff, -; the end of wram bank 0 on cgb. -; This has no significance on dmg, where wram -; isn't banked (c000-dfff is contiguous). -; However, recent versions of rgbds have replaced -; dmg-style wram with cgb wram banks. - -; Until this is fixed, this struct will have -; to be declared manually. - -wEnemyMonSpecies:: db -wEnemyMonHP:: dw -wEnemyMonPartyPos:: -wEnemyMonBoxLevel:: db -wEnemyMonStatus:: db -wEnemyMonType:: -wEnemyMonType1:: db -wEnemyMonType2:: db -wEnemyMonCatchRate_NotReferenced:: db -wEnemyMonMoves:: ds NUM_MOVES -wEnemyMonDVs:: ds 2 -wEnemyMonLevel:: db -wEnemyMonMaxHP:: dw -wEnemyMonAttack:: dw -wEnemyMonDefense:: dw -wEnemyMonSpeed:: dw -wEnemyMonSpecial:: dw -wEnemyMonPP:: ds 2 ; NUM_MOVES - 2 -SECTION "WRAM Bank 1", WRAMX, BANK[1] - ds 2 ; NUM_MOVES - 2 - -wEnemyMonBaseStats:: ds 5 -wEnemyMonCatchRate:: ds 1 -wEnemyMonBaseExp:: ds 1 - -wBattleMonNick:: ds 11 ; d009 -wBattleMon:: battle_struct wBattleMon ; d014 - - -W_TRAINERCLASS:: ; d031 - ds 1 - - ds 1 - -wTrainerPicPointer:: ; wd033 - ds 2 - ds 1 -wd036:: ds 16 -wd046:: ds 1 -wd047:: ds 1 -wd048:: ds 2 - -W_TRAINERNAME:: ; d04a -; 13 bytes for the letters of the opposing trainer -; the name is terminated with $50 with possible -; unused trailing letters - ds 13 - -W_ISINBATTLE:: ; d057 -; no battle, this is 0 -; wild battle, this is 1 -; trainer battle, this is 2 - ds 1 - -wPartyGainExpFlags:: ; d058 -; flags that indicate which party members should be be given exp when GainExperience is called - flag_array 6 - -W_CUROPPONENT:: ; d059 -; in a wild battle, this is the species of pokemon -; in a trainer battle, this is the trainer class + $C8 - ds 1 - -W_BATTLETYPE:: ; d05a -; in normal battle, this is 0 -; in old man battle, this is 1 -; in safari battle, this is 2 - ds 1 - -wDamageMultipliers:: ; d05b -; bits 0-6: Effectiveness - ; $0 = immune - ; $5 = not very effective - ; $a = neutral - ; $14 = super-effective -; bit 7: STAB - ds 1 - -W_LONEATTACKNO:: ; d05c -; which entry in LoneAttacks to use -W_GYMLEADERNO:: ; d05c -; it's actually the same thing as ^ - ds 1 -W_TRAINERNO:: ; d05d -; which instance of [youngster, lass, etc] is this? - ds 1 - -wCriticalHitOrOHKO:: ; d05e -; $00 = normal attack -; $01 = critical hit -; $02 = successful OHKO -; $ff = failed OHKO - ds 1 - -W_MOVEMISSED:: ; d05f - ds 1 - -wPlayerStatsToDouble:: ; d060 -; always 0 - ds 1 - -wPlayerStatsToHalve:: ; d061 -; always 0 - ds 1 - -W_PLAYERBATTSTATUS1:: ; d062 -; bit 0 - bide -; bit 1 - thrash / petal dance -; bit 2 - attacking multiple times (e.g. double kick) -; bit 3 - flinch -; bit 4 - charging up for attack -; bit 5 - using multi-turn move (e.g. wrap) -; bit 6 - invulnerable to normal attack (using fly/dig) -; bit 7 - confusion - ds 1 - -W_PLAYERBATTSTATUS2:: ; d063 -; bit 0 - X Accuracy effect -; bit 1 - protected by "mist" -; bit 2 - focus energy effect -; bit 4 - has a substitute -; bit 5 - need to recharge -; bit 6 - rage -; bit 7 - leech seeded - ds 1 - -W_PLAYERBATTSTATUS3:: ; d064 -; bit 0 - toxic -; bit 1 - light screen -; bit 2 - reflect -; bit 3 - tranformed - ds 1 - -wEnemyStatsToDouble:: ; d065 -; always 0 - ds 1 - -wEnemyStatsToHalve:: ; d066 -; always 0 - ds 1 - -W_ENEMYBATTSTATUS1:: ; d067 - ds 1 -W_ENEMYBATTSTATUS2:: ; d068 - ds 1 -W_ENEMYBATTSTATUS3:: ; d069 - ds 1 - -wPlayerNumAttacksLeft:: -; when the player is attacking multiple times, the number of attacks left - ds 1 - -W_PLAYERCONFUSEDCOUNTER:: ; wd06b - ds 1 - -W_PLAYERTOXICCOUNTER:: ; d06c - ds 1 -W_PLAYERDISABLEDMOVE:: ; d06d -; high nibble: which move is disabled (1-4) -; low nibble: disable turns left - ds 1 - - ds 1 - -wEnemyNumAttacksLeft:: ; d06f -; when the enemy is attacking multiple times, the number of attacks left - ds 1 - -W_ENEMYCONFUSEDCOUNTER:: ; wd070 - ds 1 - -W_ENEMYTOXICCOUNTER:: ; d071 - ds 1 -W_ENEMYDISABLEDMOVE:: ; d072 -; high nibble: which move is disabled (1-4) -; low nibble: disable turns left - ds 1 - - ds 1 - -wPlayerNumHits:: ; d074 -; number of hits by player in attacks like Double Slap, etc. - -wPlayerBideAccumulatedDamage:: ; d074 -; the amount of damage accumulated by the player while biding (2 bytes) - -wUnknownSerialCounter2:: ; d075 -; 2 bytes - - ds 4 - -wEscapedFromBattle:: -; non-zero when an item or move that allows escape from battle was used - ds 1 - -wd079:: -wAmountMoneyWon:: ds 1 ; wd079 - wd07b -wd07a:: ds 1 - ds 1 - -W_ANIMATIONID:: ; d07c -; ID number of the current battle animation - ds 1 - -wd07d:: ds 1 -wd07e:: ds 3 - -; base coordinates of frame block -W_BASECOORDX:: ; d081 - ds 1 -W_BASECOORDY:: ; d082 - ds 1 - -; low health alarm counter/enable -; high bit = enable, others = timer to cycle frequencies -wLowHealthAlarm:: ds 1 ; d083 - -W_FBTILECOUNTER:: ; d084 -; counts how many tiles of the current frame block have been drawn - ds 1 - -wd085:: ds 1 - -W_SUBANIMFRAMEDELAY:: ; d086 -; duration of each frame of the current subanimation in terms of screen refreshes - ds 1 -W_SUBANIMCOUNTER:: ; d087 -; counts the number of subentries left in the current subanimation - ds 1 - -wd088:: ds 1 - -W_NUMFBTILES:: ; d089 -; number of tiles in current battle animation frame block - ds 1 - -wTradedMonMovingRight:: ; d08a -; $01 if mon is moving from left gameboy to right gameboy; $00 if vice versa - -wd08a:: ds 1 - -wTownMapSpriteBlinkingCounter:: ; d08b - -wPartyMonAnimCounter:: ; d08b - -W_SUBANIMTRANSFORM:: ; d08b -; controls what transformations are applied to the subanimation -; 01: flip horizontally and vertically -; 02: flip horizontally and translate downwards 40 pixels -; 03: translate base coordinates of frame blocks, but don't change their internal coordinates or flip their tiles -; 04: reverse the subanimation - ds 1 - -wEndBattleWinTextPointer:: ; d08c - ds 2 - -wEndBattleLoseTextPointer:: ; d08e - ds 2 - - ds 2 - -wEndBattleTextRomBank:: ; d092 - ds 1 - - ds 1 - -W_SUBANIMADDRPTR:: ; d094 -; the address _of the address_ of the current subanimation entry - ds 2 -W_SUBANIMSUBENTRYADDR:: ; d096 -; the address of the current subentry of the current subanimation - ds 2 - - ds 2 - -wd09a:: ds 1 - -wTownMapSpriteBlinkingEnabled:: ; d09b -; non-zero when enabled. causes nest locations to blink on and off. -; the town selection cursor will blink regardless of what this value is - -wd09b:: ds 1 - -W_FBDESTADDR:: ; d09c -; current destination address in OAM for frame blocks (big endian) - ds 2 - -W_FBMODE:: ; d09e -; controls how the frame blocks are put together to form frames -; specifically, after finishing drawing the frame block, the frame block's mode determines what happens -; 00: clean OAM buffer and delay -; 02: move onto the next frame block with no delay and no cleaning OAM buffer -; 03: delay, but don't clean OAM buffer -; 04: delay, without cleaning OAM buffer, and do not advance [W_FBDESTADDR], so that the next frame block will overwrite this one -; sprite data is written column by column, each byte contains 8 columns (one for ech bit) -; for 2bpp sprites, pairs of two consecutive bytes (i.e. pairs of consecutive rows of sprite data) -; contain the upper and lower bit of each of the 8 pixels, respectively - ds 1 - -wNewTileBlockID:: ; d09f - -wd09f:: ds 1 -wd0a0:: ds 1 - -W_SPRITECURPOSX:: ; d0a1 - ds 1 -W_SPRITECURPOSY:: ; d0a2 - ds 1 -W_SPRITEWITDH:: ; d0a3 - ds 1 -W_SPRITEHEIGHT:: ; d0a4 - ds 1 -W_SPRITEINPUTCURBYTE:: ; d0a5 -; current input byte - ds 1 -W_SPRITEINPUTBITCOUNTER:: ; d0a6 -; bit offset of last read input bit - ds 1 - -W_SPRITEOUTPUTBITOFFSET:: ; d0a7; determines where in the output byte the two bits are placed. Each byte contains four columns (2bpp data) -; 3 -> XX000000 1st column -; 2 -> 00XX0000 2nd column -; 1 -> 0000XX00 3rd column -; 0 -> 000000XX 4th column - ds 1 - -W_SPRITELOADFLAGS:: ; d0a8 -; bit 0 determines used buffer (0 -> $a188, 1 -> $a310) -; bit 1 loading last sprite chunk? (there are at most 2 chunks per load operation) - ds 1 -W_SPRITEUNPACKMODE:: ; d0a9 - ds 1 -W_SPRITEFLIPPED:: ; d0aa - ds 1 - -W_SPRITEINPUTPTR:: ; d0ab -; pointer to next input byte - ds 2 -W_SPRITEOUTPUTPTR:: ; d0ad -; pointer to current output byte - ds 2 -W_SPRITEOUTPUTPTRCACHED:: ; d0af -; used to revert pointer for different bit offsets - ds 2 -W_SPRITEDECODETABLE0PTR:: ; d0b1 -; pointer to differential decoding table (assuming initial value 0) - ds 2 -W_SPRITEDECODETABLE1PTR:: ; d0b3 -; pointer to differential decoding table (assuming initial value 1) - ds 2 - -wd0b5:: ds 1 - -wNameListType:: ; d0b6 - ds 1 - -wPredefBank:: ; d0b7 - ds 1 - -W_MONHEADER:: ; d0b8 -W_MONHDEXNUM:: ; d0b8 - ds 1 - -W_MONHBASESTATS:: ; d0b9 -W_MONHBASEHP:: ; d0b9 - ds 1 -W_MONHBASEATTACK:: ; d0ba - ds 1 -W_MONHBASEDEFENSE:: ; d0bb - ds 1 -W_MONHBASESPEED:: ; d0bc - ds 1 -W_MONHBASESPECIAL:: ; d0bd - ds 1 - -W_MONHTYPES:: ; d0be -W_MONHTYPE1:: ; d0be - ds 1 -W_MONHTYPE2:: ; d0bf - ds 1 - -W_MONHCATCHRATE:: ; d0c0 - ds 1 -W_MONHBASEXP:: ; d0c1 - ds 1 -W_MONHSPRITEDIM:: ; d0c2 - ds 1 -W_MONHFRONTSPRITE:: ; d0c3 - ds 2 -W_MONHBACKSPRITE:: ; d0c5 - ds 2 - -W_MONHMOVES:: ; d0c7 - ds 4 - -W_MONHGROWTHRATE:: ; d0cb - ds 1 - -W_MONHLEARNSET:: ; d0cc -; bit field - flag_array 50 + 5 - ds 1 - -wd0d4:: ds 3 - -W_MONHPADDING:: ; d0d7 - - -W_DAMAGE:: ; d0d7 - ds 2 - -ds 2 - -wRepelRemainingSteps:: ; wd0db - ds 1 - -wMoves:: ; wd0dc -; list of moves for FormatMovesString - ds 4 - -wMoveNum:: ; d0e0 - ds 1 - -wMovesString:: ; d0e1 - ds 56 - -wd119:: ds 1 - -wWalkBikeSurfStateCopy:: ; d11a -; wWalkBikeSurfState is sometimes copied here, but it doesn't seem to be used for anything - ds 1 - -wd11b:: ds 1 -wd11c:: ds 1 -wd11d:: ds 1 -wd11e:: ds 1 -wd11f:: ds 1 - -wNumRunAttempts:: -; number of times the player has tried to run from battle - ds 1 - -wd121:: ds 1 -wd122:: ds 2 -wd124:: ds 1 - -wTextBoxID:: ; d125 - ds 1 - -wd126:: ds 1 - -W_CURENEMYLVL:: ; d127 - ds 1 - -wd128:: ds 1 -wd129:: ds 1 -wd12a:: ds 1 - -wLinkState:: ; d12b - ds 1 - -wTwoOptionMenuID:: ds 1 -wd12d:: ds 1 -wd12e:: ds 1 -wd12f:: ds 1 -wd130:: ds 1 -wd131:: ds 1 -wd132:: ds 1 -wd133:: ds 6 -wd139:: ds 1 - -wIgnoreInputCounter:: ; d13a -; counts downward each frame -; when it hits 0, bit 5 (ignore input bit) of wd730 is reset - ds 1 - -wStepCounter:: ; d13b -; counts down once every step - ds 1 - -wNumberOfNoRandomBattleStepsLeft:: ; d13c -; after a battle, you have at least 3 steps before a random battle can occur - ds 1 - -W_PRIZE1:: ; d13d - ds 1 -W_PRIZE2:: ; d13e - ds 1 -W_PRIZE3:: ; d13f - ds 1 - - ds 1 - -wSerialRandomNumberListBlock:: ; d141 -; the first 7 bytes are the preamble - -wd141:: ds 2 -wd143:: ds 2 -wd145:: ds 3 - -wLinkBattleRandomNumberList:: ; d148 -; shared list of 9 random numbers, indexed by wLinkBattleRandomNumberListIndex - ds 10 - -wSerialPlayerDataBlock:: ; d152 -; the first 6 bytes are the preamble - -wd152:: ds 1 -wd153:: ds 3 -wd156:: ds 1 -wd157:: ds 1 - - -wPlayerName:: ; d158 - ds 11 - -wPartyCount:: ds 1 ; d163 -wPartySpecies:: ds PARTY_LENGTH ; d164 -wPartyEnd:: ds 1 ; d16a - -wPartyMons:: -wPartyMon1:: party_struct wPartyMon1 ; d16b -wPartyMon2:: party_struct wPartyMon2 ; d197 -wPartyMon3:: party_struct wPartyMon3 ; d1c3 -wPartyMon4:: party_struct wPartyMon4 ; d1ef -wPartyMon5:: party_struct wPartyMon5 ; d21b -wPartyMon6:: party_struct wPartyMon6 ; d247 - -wPartyMonOT:: ds 11 * PARTY_LENGTH ; d273 -wPartyMonNicks:: ds 11 * PARTY_LENGTH ; d2b5 - - -wPokedexOwned:: ; d2f7 - flag_array NUM_POKEMON -wPokedexOwnedEnd:: - -wPokedexSeen:: ; d30a - flag_array NUM_POKEMON -wPokedexSeenEnd:: - - -wNumBagItems:: ; d31d - ds 1 -wBagItems:: ; d31e -; item, quantity - ds 20 * 2 - ds 1 ; end - -wPlayerMoney:: ; d347 - ds 3 ; BCD - -W_RIVALNAME:: ; d34a - ds 11 - -W_OPTIONS:: ; d355 -; bit 7 = battle animation -; 0: On -; 1: Off -; bit 6 = battle style -; 0: Shift -; 1: Set -; bits 0-3 = text speed (number of frames to delay after printing a letter) -; 1: Fast -; 3: Medium -; 5: Slow - ds 1 - -W_OBTAINEDBADGES:: ; d356 - ds 1 - - ds 1 - -wd358:: ds 1 - -wPlayerID:: ; d359 - ds 2 - -wd35b:: ds 1 -wd35c:: ds 1 - -wMapPalOffset:: ; d35d -; offset subtracted from FadePal4 to get the background and object palettes for the current map -; normally, it is 0. it is 6 when Flash is needed, causing FadePal2 to be used instead of FadePal4 - ds 1 - -W_CURMAP:: ; d35e - ds 1 - -wCurrentTileBlockMapViewPointer:: ; d35f -; pointer to the upper left corner of the current view in the tile block map - ds 2 - -W_YCOORD:: ; d361 -; player’s position on the current map - ds 1 - -W_XCOORD:: ; d362 - ds 1 - -W_YBLOCKCOORD:: ; d363 -; player's y position (by block) - ds 1 - -W_XBLOCKCOORD:: ; d364 - ds 1 - -wLastMap:: ; d365 - ds 1 - -wd366:: ds 1 - -W_CURMAPTILESET:: ; d367 - ds 1 - -W_CURMAPHEIGHT:: ; d368 -; blocks - ds 1 - -W_CURMAPWIDTH:: ; d369 -; blocks - ds 1 - -W_MAPDATAPTR:: ; d36a - ds 2 - -W_MAPTEXTPTR:: ; d36c - ds 2 - -W_MAPSCRIPTPTR:: ; d36e - ds 2 - -W_MAPCONNECTIONS:: ; d370 -; connection byte - ds 1 - -W_MAPCONN1PTR:: ; d371 - ds 1 - -wd372:: ds 1 -wd373:: ds 1 -wd374:: ds 1 -wd375:: ds 1 -wd376:: ds 1 -wd377:: ds 1 -wd378:: ds 1 -wd379:: ds 1 -wd37a:: ds 1 -wd37b:: ds 1 - -W_MAPCONN2PTR:: ; d37c - ds 1 - -wd37d:: ds 1 -wd37e:: ds 1 -wd37f:: ds 1 -wd380:: ds 1 -wd381:: ds 1 -wd382:: ds 1 -wd383:: ds 1 -wd384:: ds 1 -wd385:: ds 1 -wd386:: ds 1 - -W_MAPCONN3PTR:: ; d387 - ds 1 - -wd388:: ds 1 -wd389:: ds 1 -wd38a:: ds 1 -wd38b:: ds 1 -wd38c:: ds 1 -wd38d:: ds 1 -wd38e:: ds 1 -wd38f:: ds 1 -wd390:: ds 1 -wd391:: ds 1 - -W_MAPCONN4PTR:: ; d392 - ds 1 - -wd393:: ds 1 -wd394:: ds 1 -wd395:: ds 1 -wd396:: ds 1 -wd397:: ds 1 -wd398:: ds 1 -wd399:: ds 1 -wd39a:: ds 1 -wd39b:: ds 1 -wd39c:: ds 1 - -W_SPRITESET:: ; d39d -; sprite set for the current map (11 sprite picture ID's) - ds 11 - -W_SPRITESETID:: ; d3a8 -; sprite set ID for the current map - ds 1 - -wd3a9:: ds 1 -wd3aa:: ds 3 -wd3ad:: ds 1 - -wNumberOfWarps:: ; d3ae -; number of warps in current map - ds 1 - -wWarpEntries:: ; d3af -; current map warp entries - ds 128 - -wDestinationWarpID:: ; d42f -; if $ff, the player's coordinates are not updated when entering the map - ds 1 - - ds 4 - -wd435:: ds 1 -wd436:: ds 1 - - ds 122 - -wd4b0:: ds 1 -wd4b1:: ds 32 -wd4d1:: ds 16 - -W_NUMSPRITES:: ; d4e1 -; number of sprites on the current map - ds 1 - -; these two variables track the X and Y offset in blocks from the last special warp used -; they don't seem to be used for anything -wYOffsetSinceLastSpecialWarp:: ; d4e2 - ds 1 -wXOffsetSinceLastSpecialWarp:: ; d4e3 - ds 1 - -W_MAPSPRITEDATA:: ; d4e4 -; two bytes per sprite (movement byte 2, text ID) - ds 32 - -W_MAPSPRITEEXTRADATA:: ; d504 -; two bytes per sprite (trainer class/item ID, trainer set ID) - ds 32 - -wd524:: ds 1 -wd525:: ds 1 - -wMapViewVRAMPointer:: ; d526 -; the address of the upper left corner of the visible portion of the BG tile map in VRAM - ds 2 - -wd528:: ds 1 -wd529:: ds 1 -wd52a:: ds 1 - -W_TILESETBANK:: ; d52b - ds 1 - -W_TILESETBLOCKSPTR:: ; d52c -; maps blocks (4x4 tiles) to tiles - ds 2 - -W_TILESETGFXPTR:: ; d52e - ds 2 - -W_TILESETCOLLISIONPTR:: ; d530 -; list of all walkable tiles - ds 2 - -W_TILESETTALKINGOVERTILES:: ; d532 - ds 3 - -W_GRASSTILE:: ; d535 - ds 1 - - ds 4 - -wNumBoxItems:: ; d53a - ds 1 -wBoxItems:: ; d53b -; item, quantity - ds 50 * 2 - ds 1 ; end - -wd5a0:: ds 2 -wd5a2:: ds 1 -wd5a3:: ds 1 - -wPlayerCoins:: ; d5a4 - ds 2 ; BCD - -W_MISSABLEOBJECTFLAGS:: ; d5a6 -; bit array of missable objects. set = removed - ds 39 - -wd5cd:: ds 1 - -W_MISSABLEOBJECTLIST:: ; d5ce -; each entry consists of 2 bytes -; * the sprite ID (depending on the current map) -; * the missable object index (global, used for W_MISSABLEOBJECTFLAGS) -; terminated with $FF - ds 17 * 2 - -W_GAMEPROGRESSFLAGS:: ; d5f0 -; $c8 bytes - ds 0 - -W_OAKSLABCURSCRIPT:: ; d5f0 - ds 1 -W_PALLETTOWNCURSCRIPT:: ; d5f1 - ds 1 - ds 1 -W_BLUESHOUSECURSCRIPT:: ; d5f3 - ds 1 -W_VIRIDIANCITYCURSCRIPT:: ; d5f4 - ds 1 - ds 2 -W_PEWTERCITYCURSCRIPT:: ; d5f7 - ds 1 -W_ROUTE3CURSCRIPT:: ; d5f8 - ds 1 -W_ROUTE4CURSCRIPT:: ; d5f9 - ds 1 - ds 1 -W_VIRIDIANGYMCURSCRIPT:: ; d5fb - ds 1 -W_PEWTERGYMCURSCRIPT:: ; d5fc - ds 1 -W_CERULEANGYMCURSCRIPT:: ; d5fd - ds 1 -W_VERMILIONGYMCURSCRIPT:: ; d5fe - ds 1 -W_CELADONGYMCURSCRIPT:: ; d5ff - ds 1 -W_ROUTE6CURSCRIPT:: ; d600 - ds 1 -W_ROUTE8CURSCRIPT:: ; d601 - ds 1 -W_ROUTE24CURSCRIPT:: ; d602 - ds 1 -W_ROUTE25CURSCRIPT:: ; d603 - ds 1 -W_ROUTE9CURSCRIPT:: ; d604 - ds 1 -W_ROUTE10CURSCRIPT:: ; d605 - ds 1 -W_MTMOON1CURSCRIPT:: ; d606 - ds 1 -W_MTMOON3CURSCRIPT:: ; d607 - ds 1 -W_SSANNE8CURSCRIPT:: ; d608 - ds 1 -W_SSANNE9CURSCRIPT:: ; d609 - ds 1 -W_ROUTE22CURSCRIPT:: ; d60a - ds 1 - ds 1 -W_REDSHOUSE2CURSCRIPT:: ; d60c - ds 1 -W_VIRIDIANMARKETCURSCRIPT:: ; d60d - ds 1 -W_ROUTE22GATECURSCRIPT:: ; d60e - ds 1 -W_CERULEANCITYCURSCRIPT:: ; d60f - ds 1 - ds 7 -W_SSANNE5CURSCRIPT:: ; d617 - ds 1 -W_VIRIDIANFORESTCURSCRIPT:: ; d618 - ds 1 -W_MUSEUM1FCURSCRIPT:: ; d619 - ds 1 -W_ROUTE13CURSCRIPT:: ; d61a - ds 1 -W_ROUTE14CURSCRIPT:: ; d61b - ds 1 -W_ROUTE17CURSCRIPT:: ; d61c - ds 1 -W_ROUTE19CURSCRIPT:: ; d61d - ds 1 -W_ROUTE21CURSCRIPT:: ; d61e - ds 1 -W_SAFARIZONEENTRANCECURSCRIPT:: ; d61f - ds 1 -W_ROCKTUNNEL2CURSCRIPT:: ; d620 - ds 1 -W_ROCKTUNNEL1CURSCRIPT:: ; d621 - ds 1 - ds 1 -W_ROUTE11CURSCRIPT:: ; d623 - ds 1 -W_ROUTE12CURSCRIPT:: ; d624 - ds 1 -W_ROUTE15CURSCRIPT:: ; d625 - ds 1 -W_ROUTE16CURSCRIPT:: ; d626 - ds 1 -W_ROUTE18CURSCRIPT:: ; d627 - ds 1 -W_ROUTE20CURSCRIPT:: ; d628 - ds 1 -W_SSANNE10CURSCRIPT:: ; d629 - ds 1 -W_VERMILIONCITYCURSCRIPT:: ; d62a - ds 1 -W_POKEMONTOWER2CURSCRIPT:: ; d62b - ds 1 -W_POKEMONTOWER3CURSCRIPT:: ; d62c - ds 1 -W_POKEMONTOWER4CURSCRIPT:: ; d62d - ds 1 -W_POKEMONTOWER5CURSCRIPT:: ; d62e - ds 1 -W_POKEMONTOWER6CURSCRIPT:: ; d62f - ds 1 -W_POKEMONTOWER7CURSCRIPT:: ; d630 - ds 1 -W_ROCKETHIDEOUT1CURSCRIPT:: ; d631 - ds 1 -W_ROCKETHIDEOUT2CURSCRIPT:: ; d632 - ds 1 -W_ROCKETHIDEOUT3CURSCRIPT:: ; d633 - ds 1 -W_ROCKETHIDEOUT4CURSCRIPT:: ; d634 - ds 2 -W_ROUTE6GATECURSCRIPT:: ; d636 - ds 1 -W_ROUTE8GATECURSCRIPT:: ; d637 - ds 2 -W_CINNABARISLANDCURSCRIPT:: ; d639 - ds 1 -W_MANSION1CURSCRIPT:: ; d63a - ds 2 -W_MANSION2CURSCRIPT:: ; d63c - ds 1 -W_MANSION3CURSCRIPT:: ; d63d - ds 1 -W_MANSION4CURSCRIPT:: ; d63e - ds 1 -W_VICTORYROAD2CURSCRIPT:: ; d63f - ds 1 -W_VICTORYROAD3CURSCRIPT:: ; d640 - ds 2 -W_FIGHTINGDOJOCURSCRIPT:: ; d642 - ds 1 -W_SILPHCO2CURSCRIPT:: ; d643 - ds 1 -W_SILPHCO3CURSCRIPT:: ; d644 - ds 1 -W_SILPHCO4CURSCRIPT:: ; d645 - ds 1 -W_SILPHCO5CURSCRIPT:: ; d646 - ds 1 -W_SILPHCO6CURSCRIPT:: ; d647 - ds 1 -W_SILPHCO7CURSCRIPT:: ; d648 - ds 1 -W_SILPHCO8CURSCRIPT:: ; d649 - ds 1 -W_SILPHCO9CURSCRIPT:: ; d64a - ds 1 -W_HALLOFFAMEROOMCURSCRIPT:: ; d64b - ds 1 -W_GARYCURSCRIPT:: ; d64c - ds 1 -W_LORELEICURSCRIPT:: ; d64d - ds 1 -W_BRUNOCURSCRIPT:: ; d64e - ds 1 -W_AGATHACURSCRIPT:: ; d64f - ds 1 -W_UNKNOWNDUNGEON3CURSCRIPT:: ; d650 - ds 1 -W_VICTORYROAD1CURSCRIPT:: ; d651 - ds 1 - ds 1 -W_LANCECURSCRIPT:: ; d653 - ds 1 - ds 4 -W_SILPHCO10CURSCRIPT:: ; d658 - ds 1 -W_SILPHCO11CURSCRIPT:: ; d659 - ds 1 - ds 1 -W_FUCHSIAGYMCURSCRIPT:: ; d65b - ds 1 -W_SAFFRONGYMCURSCRIPT:: ; d65c - ds 1 - ds 1 -W_CINNABARGYMCURSCRIPT:: ; d65e - ds 1 -W_CELADONGAMECORNERCURSCRIPT:: ; d65f - ds 1 -W_ROUTE16GATECURSCRIPT:: ; d660 - ds 1 -W_BILLSHOUSECURSCRIPT:: ; d661 - ds 1 -W_ROUTE5GATECURSCRIPT:: ; d662 - ds 1 -W_POWERPLANTCURSCRIPT:: ; d663 -; overload - ds 0 -W_ROUTE7GATECURSCRIPT:: ; d663 -; overload - ds 1 - ds 1 -W_SSANNE2CURSCRIPT:: ; d665 - ds 1 -W_SEAFOAMISLANDS4CURSCRIPT:: ; d666 - ds 1 -W_ROUTE23CURSCRIPT:: ; d667 - ds 1 -W_SEAFOAMISLANDS5CURSCRIPT:: ; d668 - ds 1 -W_ROUTE18GATECURSCRIPT:: ; d669 - ds 1 - - ds 134 - -wd6f0:: ds 14 -wd6fe:: ds 2 - -wWalkBikeSurfState:: ; d700 -; $00 = walking -; $01 = biking -; $02 = surfing - ds 1 - - ds 10 - -W_TOWNVISITEDFLAG:: ; d70b - flag_array 13 - -wSafariSteps:: ; d70d -; starts at 502 - ds 2 - -W_FOSSILITEM:: ; d70f -; item given to cinnabar lab - ds 1 - -W_FOSSILMON:: ; d710 -; mon that will result from the item - ds 1 - - ds 2 - -W_ENEMYMONORTRAINERCLASS:: ; d713 -; trainer classes start at $c8 - ds 1 - -wPlayerJumpingYScreenCoordsIndex:: ; d714 - ds 1 - -W_RIVALSTARTER:: ; d715 - ds 1 - - ds 1 - -W_PLAYERSTARTER:: ; d717 - ds 1 - -wBoulderSpriteIndex:: ; d718 -; sprite index of the boulder the player is trying to push - ds 1 - -wLastBlackoutMap:: ; d719 - ds 1 - -wDestinationMap:: ; d71a -; destination map (for certain types of special warps, not ordinary walking) - ds 1 - -wd71b:: ds 1 - -wTileInFrontOfBoulderAndBoulderCollisionResult:: ; d71c -; used to store the tile in front of the boulder when trying to push a boulder -; also used to store the result of the collision check ($ff for a collision and $00 for no collision) - ds 1 - -wDungeonWarpDestinationMap:: ; d71d -; destination map for dungeon warps - ds 1 - -wWhichDungeonWarp:: ; d71e -; which dungeon warp within the source map was used - ds 1 - -wd71f:: ds 9 - -wd728:: -; bit 0: using Strength outside of battle - ds 1 - - ds 1 - -wd72a:: ds 2 - -wd72c:: ; d72c -; bit 0: if not set, the 3 minimum steps between random battles have passed - ds 1 - -wd72d:: ds 1 -wd72e:: ds 2 - -wd730:: -; bit 0: NPC sprite being moved by script -; bit 5: ignore joypad input -; bit 6: print text with no delay between each letter -; bit 7: set if joypad states are being simulated in the overworld - ds 1 - - ds 1 - -wd732:: ; d732 -; bit 0: play time being counted -; bit 1: remnant of debug mode? not set by the game code. -; if it is set -; 1. skips most of Prof. Oak's speech, and uses NINTEN as the player's name and SONY as the rival's name -; 2. does not have the player start in floor two of the playyer's house (instead sending them to [wLastMap]) -; 3. allows wild battles to be avoided by holding down B -; bit 2: the target warp is a fly warp (bit 3 set or blacked out) or a dungeon warp (bit 4 set) -; bit 3: used warp pad, escape rope, dig, teleport, or fly, so the target warp is a "fly warp" -; bit 4: jumped into hole (Pokemon Mansion, Seafoam Islands, Victory Road) or went down waterfall (Seafoam Islands), so the target warp is a "dungeon warp" -; bit 5: currently being forced to ride bike (cycling road) -; bit 6: map destination is [wLastBlackoutMap] (usually the last used pokemon center, but could be the player's house) - ds 1 - -W_FLAGS_D733:: ; d733 -; bit 4: use variable [W_CURMAPSCRIPT] instead of the provided index for next frame's map script (used to start battle when talking to trainers) -; bit 7: used fly out of battle - ds 1 - -wd734:: ds 2 - -wd736:: ; d736 -; bit 0: check if the player is standing on a door and make him walk down a step if so -; bit 1: the player is currently stepping down from a door -; bit 2: standing on a warp -; bit 6: jumping down a ledge - ds 1 - -wCompletedInGameTradeFlags:: ; d737 - ds 2 - - ds 2 - -wd73b:: ds 1 -wd73c:: ds 3 - -wCardKeyDoorY:: ; d73f - ds 1 - -wCardKeyDoorX:: ; d740 - ds 1 - - ds 2 - -wd743:: ds 1 -wd744:: ds 3 -wd747:: ds 3 -wd74a:: ds 1 - -wd74b:: ; d74b -; bit 0: Prof. Oak has lead the player to the north end of his lab -; bit 1: Prof. Oak has asked the player to choose a pokemon -; bit 2: the player and the rival have received their pokemon -; bit 3: the player has battled the rival in Oak's lab -; bit 4: Prof. Oak has given the player 5 pokeballs -; bit 5: received pokedex - ds 1 - -wd74c:: ds 2 -wd74e:: ds 3 -wd751:: ds 1 -wd752:: ds 2 -wd754:: ds 1 -wd755:: ds 5 -wd75a:: ds 1 -wd75b:: ds 3 -wd75e:: ds 1 -wd75f:: ds 5 -wd764:: ds 1 -wd765:: ds 1 -wd766:: ds 1 -wd767:: ds 1 -wd768:: ds 1 -wd769:: ds 3 -wd76c:: ds 5 -wd771:: ds 2 -wd773:: ds 4 -wd777:: ds 1 -wd778:: ds 4 -wd77c:: ds 1 -wd77d:: ds 1 -wd77e:: ds 5 -wd783:: ds 11 -wd78e:: ds 2 -wd790:: ds 2 -wd792:: ds 4 -wd796:: ds 2 -wd798:: ds 2 -wd79a:: ds 1 -wd79b:: ds 1 -wd79c:: ds 5 -wd7a1:: ds 2 -wd7a3:: ds 12 -wd7af:: ds 2 -wd7b1:: ds 2 -wd7b3:: ds 1 -wd7b4:: ds 5 -wd7b9:: ds 4 -wd7bd:: ds 2 -wd7bf:: ds 3 -wd7c2:: ds 1 -wd7c3:: ds 2 -wd7c5:: ds 1 -wd7c6:: ds 3 -wd7c9:: ds 4 -wd7cd:: ds 2 -wd7cf:: ds 2 -wd7d1:: ds 1 -wd7d2:: ds 1 -wd7d3:: ds 2 -wd7d5:: ds 1 -wd7d6:: ds 1 -wd7d7:: ds 1 -wd7d8:: ds 1 -wd7d9:: ds 2 -wd7db:: ds 2 -wd7dd:: ds 2 -wd7df:: ds 1 -wd7e0:: ds 1 -wd7e1:: ds 2 -wd7e3:: ds 2 -wd7e5:: ds 2 -wd7e7:: ds 1 -wd7e8:: ds 1 -wd7e9:: ds 2 -wd7eb:: ds 2 -wd7ed:: ds 1 -wd7ee:: ds 1 -wd7ef:: ds 1 -wd7f0:: ds 1 -wd7f1:: ds 1 -wd7f2:: ds 1 -wd7f3:: ds 2 -wd7f5:: ds 1 -wd7f6:: ds 9 -wd7ff:: ds 4 -wd803:: ds 2 -wd805:: ds 2 -wd807:: ds 2 -wd809:: ds 10 -wd813:: ds 2 -wd815:: ds 1 -wd816:: ds 1 -wd817:: ds 2 -wd819:: ds 2 -wd81b:: ds 10 -wd825:: ds 1 -wd826:: ds 1 -wd827:: ds 1 -wd828:: ds 1 -wd829:: ds 1 -wd82a:: ds 1 -wd82b:: ds 1 -wd82c:: ds 1 -wd82d:: ds 1 -wd82e:: ds 1 -wd82f:: ds 1 -wd830:: ds 1 -wd831:: ds 1 -wd832:: ds 1 -wd833:: ds 1 -wd834:: ds 1 -wd835:: ds 1 -wd836:: ds 1 -wd837:: ds 1 -wd838:: ds 15 -wd847:: ds 2 -wd849:: ds 2 -wd84b:: ds 12 -wd857:: ds 8 -wd85f:: ds 4 -wd863:: ds 1 -wd864:: ds 1 -wd865:: ds 1 -wd866:: ds 1 -wd867:: ds 2 -wd869:: ds 20 -wd87d:: ds 2 -wd87f:: ds 1 -wd880:: ds 1 -wd881:: ds 1 -wd882:: ds 5 - -wLinkEnemyTrainerName:: ; d887 -; linked game's trainer name - -W_GRASSRATE:: ; d887 - ds 1 - -W_GRASSMONS:: ; d888 - ds 20 - - -wEnemyPartyCount:: ds 1 ; d89c -wEnemyPartyMons:: ds PARTY_LENGTH + 1 ; d89d - -wEnemyMons:: ; d8a4 -wEnemyMon1:: party_struct wEnemyMon1 -wEnemyMon2:: party_struct wEnemyMon2 -wEnemyMon3:: party_struct wEnemyMon3 -wEnemyMon4:: party_struct wEnemyMon4 -wEnemyMon5:: party_struct wEnemyMon5 -wEnemyMon6:: party_struct wEnemyMon6 - -wEnemyMonOT:: ds 11 * PARTY_LENGTH ; d9ac -wEnemyMonNicks:: ds 11 * PARTY_LENGTH ; d9ee - - -W_TRAINERHEADERPTR:: ; da30 - ds 2 - - ds 6 - -wda38:: ds 1 - -W_CURMAPSCRIPT:: ; da39 -; index of current map script, mostly used as index for function pointer array -; mostly copied from map-specific map script pointer and wirtten back later - ds 1 - - ds 6 - -W_PLAYTIMEHOURS:: ; da40 - ds 2 -W_PLAYTIMEMINUTES:: ; da42 - ds 2 -W_PLAYTIMESECONDS:: ; da44 - ds 1 -W_PLAYTIMEFRAMES:: ; da45 - ds 1 - -wSafariZoneGameOver:: ; da46 - ds 1 - -W_NUMSAFARIBALLS:: ; da47 - ds 1 - - -W_DAYCARE_IN_USE:: ; da48 -; 0 if no pokemon is in the daycare -; 1 if pokemon is in the daycare - ds 1 - -W_DAYCAREMONNAME:: ds 11 ; da49 -W_DAYCAREMONOT:: ds 11 ; da54 - -wDayCareMon:: box_struct wDayCareMon ; da5f - - -W_NUMINBOX:: ds 1 ; da80 -wBoxSpecies:: ds MONS_PER_BOX + 1 - -wBoxMons:: -wBoxMon1:: box_struct wBoxMon1 ; da96 -wBoxMon2:: ds box_struct_length * (MONS_PER_BOX + -1) ; dab7 - -wBoxMonOT:: ds 11 * MONS_PER_BOX ; dd2a -wBoxMonNicks:: ds 11 * MONS_PER_BOX ; de06 -wBoxMonNicksEnd:: ; dee2 - - -SECTION "Stack", WRAMX[$dfff], BANK[1] -wStack:: ; dfff - ds -$100 - - -INCLUDE "sram.asm" +
+INCLUDE "constants.asm"
+
+flag_array: MACRO
+ ds ((\1) + 7) / 8
+ENDM
+
+box_struct_length EQU 25 + NUM_MOVES * 2
+box_struct: MACRO
+\1Species:: db
+\1HP:: dw
+\1BoxLevel:: db
+\1Status:: db
+\1Type::
+\1Type1:: db
+\1Type2:: db
+\1CatchRate:: db
+\1Moves:: ds NUM_MOVES
+\1OTID:: dw
+\1Exp:: ds 3
+\1HPExp:: dw
+\1AttackExp:: dw
+\1DefenseExp:: dw
+\1SpeedExp:: dw
+\1SpecialExp:: dw
+\1DVs:: ds 2
+\1PP:: ds NUM_MOVES
+ENDM
+
+party_struct: MACRO
+ box_struct \1
+\1Level:: db
+\1Stats::
+\1MaxHP:: dw
+\1Attack:: dw
+\1Defense:: dw
+\1Speed:: dw
+\1Special:: dw
+ENDM
+
+battle_struct: MACRO
+\1Species:: db
+\1HP:: dw
+\1BoxLevel:: db
+\1Status:: db
+\1Type::
+\1Type1:: db
+\1Type2:: db
+\1CatchRate:: db
+\1Moves:: ds NUM_MOVES
+\1DVs:: ds 2
+\1Level:: db
+\1MaxHP:: dw
+\1Attack:: dw
+\1Defense:: dw
+\1Speed:: dw
+\1Special:: dw
+\1PP:: ds NUM_MOVES
+ENDM
+
+
+SECTION "WRAM Bank 0", WRAM0
+
+wc000:: ds 1
+wc001:: ds 1
+wc002:: ds 1
+wc003:: ds 1
+wc004:: ds 1
+wc005:: ds 1
+wc006:: ds 8
+wc00e:: ds 4
+wc012:: ds 4
+wc016:: ds 16
+wc026:: ds 1
+wc027:: ds 1
+wc028:: ds 2
+wc02a:: ds 1
+wc02b:: ds 1
+wc02c:: ds 1
+wc02d:: ds 1
+wc02e:: ds 8
+wc036:: ds 8
+wc03e:: ds 8
+wc046:: ds 8
+wc04e:: ds 8
+wc056:: ds 8
+wc05e:: ds 8
+wc066:: ds 8
+wc06e:: ds 8
+wc076:: ds 8
+wc07e:: ds 8
+wc086:: ds 8
+wc08e:: ds 8
+wc096:: ds 8
+wc09e:: ds 8
+wc0a6:: ds 8
+wc0ae:: ds 8
+wc0b6:: ds 8
+wc0be:: ds 8
+wc0c6:: ds 8
+wc0ce:: ds 1
+wc0cf:: ds 1
+wc0d0:: ds 1
+wc0d1:: ds 1
+wc0d2:: ds 1
+wc0d3:: ds 1
+wc0d4:: ds 1
+wc0d5:: ds 1
+wc0d6:: ds 8
+wc0de:: ds 8
+wc0e6:: ds 1
+wc0e7:: ds 1
+wc0e8:: ds 1
+wc0e9:: ds 1
+wc0ea:: ds 1
+wc0eb:: ds 1
+wc0ec:: ds 1
+wc0ed:: ds 1
+wc0ee:: ds 1
+wc0ef:: ds 1
+wc0f0:: ds 1
+wc0f1:: ds 1
+wc0f2:: ds 14
+
+
+SECTION "Sprite State Data", WRAM0[$c100]
+
+wSpriteStateData1:: ; c100
+; data for all sprites on the current map
+; holds info for 16 sprites with $10 bytes each
+; player sprite is always sprite 0
+; C1x0: picture ID (fixed, loaded at map init)
+; C1x1: movement status (0: uninitialized, 1: ready, 2: delayed, 3: moving)
+; C1x2: sprite image index (changed on update, $ff if off screen, includes facing direction, progress in walking animation and a sprite-specific offset)
+; C1x3: Y screen position delta (-1,0 or 1; added to c1x4 on each walking animation update)
+; C1x4: Y screen position (in pixels, always 4 pixels above grid which makes sprites appear to be in the center of a tile)
+; C1x5: X screen position delta (-1,0 or 1; added to c1x6 on each walking animation update)
+; C1x6: X screen position (in pixels, snaps to grid if not currently walking)
+; C1x7: intra-animation-frame counter (counting upwards to 4 until c1x8 is incremented)
+; C1x8: animation frame counter (increased every 4 updates, hold four states (totalling to 16 walking frames)
+; C1x9: facing direction (0: down, 4: up, 8: left, $c: right)
+; C1xA
+; C1xB
+; C1xC
+; C1xD
+; C1xE
+; C1xF
+ ds $10 * $10
+
+
+SECTION "Sprite State Data 2", WRAM0[$c200]
+
+wSpriteStateData2:: ; c200
+; more data for all sprites on the current map
+; holds info for 16 sprites with $10 bytes each
+; player sprite is always sprite 0
+; C2x0: walk animation counter (counting from $10 backwards when moving)
+; C2x1:
+; C2x2: Y displacement (initialized at 8, supposed to keep moving sprites from moving too far, but bugged)
+; C2x3: X displacement (initialized at 8, supposed to keep moving sprites from moving too far, but bugged)
+; C2x4: Y position (in 2x2 tile grid steps, topmost 2x2 tile has value 4)
+; C2x5: X position (in 2x2 tile grid steps, leftmost 2x2 tile has value 4)
+; C2x6: movement byte 1 (determines whether a sprite can move, $ff:not moving, $fe:random movements, others unknown)
+; C2x7: (?) (set to $80 when in grass, else $0; may be used to draw grass above the sprite)
+; C2x8: delay until next movement (counted downwards, status (c1x1) is set to ready if reached 0)
+; C2x9
+; C2xA
+; C2xB
+; C2xC
+; C2xD
+; C2xE: sprite image base offset (in video ram, player always has value 1, used to compute c1x2)
+; C2xF
+ ds $10 * $10
+
+
+SECTION "OAM Buffer", WRAM0[$c300]
+
+wOAMBuffer:: ; c300
+; buffer for OAM data. Copied to OAM by DMA
+ ds 4 * 40
+
+wTileMap:: ; c3a0
+; buffer for tiles that are visible on screen (20 columns by 18 rows)
+ ds 20 * 18
+
+wSerialPartyMonsPatchList:: ; c508
+; list of indexes to patch with SERIAL_NO_DATA_BYTE after transfer
+
+wTileMapBackup:: ; c508
+; buffer for temporarily saving and restoring current screen's tiles
+; (e.g. if menus are drawn on top)
+; ds 20 * 18
+
+ ds 200
+
+wSerialEnemyMonsPatchList:: ; c5d0
+; list of indexes to patch with SERIAL_NO_DATA_BYTE after transfer
+ ds 200
+
+ ds 80
+
+wTempPic::
+wOverworldMap:: ; c6e8
+ ds 1300
+
+wScreenEdgeTiles:: ; cbfc
+; the tiles of the row or column to be redrawn by RedrawExposedScreenEdge
+ ds 20 * 2
+
+; coordinates of the position of the cursor for the top menu item (id 0)
+wTopMenuItemY:: ; cc24
+ ds 1
+wTopMenuItemX:: ; cc25
+ ds 1
+
+wCurrentMenuItem:: ; cc26
+; the id of the currently selected menu item
+; the top item has id 0, the one below that has id 1, etc.
+; note that the "top item" means the top item currently visible on the screen
+; add this value to [wListScrollOffset] to get the item's position within the list
+ ds 1
+
+wTileBehindCursor:: ; cc27
+; the tile that was behind the menu cursor's current location
+ ds 1
+
+wMaxMenuItem:: ; cc28
+; id of the bottom menu item
+ ds 1
+
+wMenuWatchedKeys:: ; cc29
+; bit mask of keys that the menu will respond to
+ ds 1
+
+wLastMenuItem:: ; cc2a
+; id of previously selected menu item
+ ds 1
+
+wcc2b:: ds 1
+wcc2c:: ds 1
+wcc2d:: ds 1
+
+wPlayerMoveListIndex:: ; cc2e
+ ds 1
+
+wPlayerMonNumber:: ; cc2f
+ ds 1
+
+wMenuCursorLocation:: ; cc30
+; the address of the menu cursor's current location within wTileMap
+ ds 2
+
+ ds 2
+
+wMenuJoypadPollCount:: ; cc34
+; how many times should HandleMenuInput poll the joypad state before it returns?
+ ds 1
+
+wMenuItemToSwap:: ; cc35
+; id of menu item selected for swapping (counts from 1) (0 means that no menu item has been selected for swapping)
+ ds 1
+
+wListScrollOffset:: ; cc36
+; offset of the current top menu item from the beginning of the list
+; keeps track of what section of the list is on screen
+ ds 1
+
+wcc37:: ds 1
+
+wTradeCenterPointerTableIndex:: ; cc38
+ ds 1
+
+ ds 1
+
+wcc3a:: ds 1
+wcc3b:: ds 1
+
+wDoNotWaitForButtonPressAfterDisplayingText:: ; cc3c
+; if non-zero, skip waiting for a button press after displaying text in DisplayTextID
+ ds 1
+
+wSerialSyncAndExchangeNybbleReceiveData:: ; cc3d
+; the final received nybble is stored here by Serial_SyncAndExchangeNybble
+
+wSerialExchangeNybbleTempReceiveData:: ; cc3d
+; temporary nybble used by Serial_ExchangeNybble
+
+wLinkMenuSelectionReceiveBuffer:: ; cc3d
+; two byte buffer
+; the received menu selection is stored twice
+
+wcc3d:: ds 1
+
+wSerialExchangeNybbleReceiveData:: ; cc3e
+; the final received nybble is stored here by Serial_ExchangeNybble
+ ds 1
+
+ ds 3
+
+wSerialExchangeNybbleSendData:: ; cc42
+; this nybble is sent when using Serial_SyncAndExchangeNybble or Serial_ExchangeNybble
+
+wLinkMenuSelectionSendBuffer:: ; cc42
+; two byte buffer
+; the menu selection byte is stored twice before sending
+
+ ds 5
+
+wLinkTimeoutCounter:: ; cc47
+; 1 byte
+
+wUnknownSerialCounter:: ; cc47
+; 2 bytes
+
+wcc47:: ds 1
+wcc48:: ds 1
+
+wWhichTradeMonSelectionMenu:: ; cc49
+; $00 = player mons
+; $01 = enemy mons
+
+wcc49:: ds 1
+
+wMenuWrappingEnabled:: ; cc4a
+; set to 1 if you can go from the bottom to the top or top to bottom of a menu
+; set to 0 if you can't go past the top or bottom of the menu
+ ds 1
+
+wcc4b:: ds 2
+wcc4d:: ds 1
+
+wPredefID:: ; cc4e
+ ds 1
+wPredefRegisters:: ; cc4f
+ ds 6
+
+wTrainerHeaderFlagBit:: ; cc55
+ ds 1
+
+ ds 1
+
+wNPCMovementScriptPointerTableNum:: ; cc57
+; which NPC movement script pointer is being used
+; 0 if an NPC movement script is not running
+ ds 1
+
+wNPCMovementScriptBank:: ; cc58
+; ROM bank of current NPC movement script
+ ds 1
+
+ ds 2
+
+wHallOfFame:: ; cc5b
+wBoostExpByExpAll:: ; cc5b
+wAnimationType:: ; cc5b
+; values between 0-6. Shake screen horizontally, shake screen vertically, blink Pokemon...
+
+wcc5b:: ds 1
+wcc5c:: ds 1
+wcc5d:: ds 1
+wcc5e:: ds 13
+
+wcc6b:: ds 14
+wcc79:: ds 30
+
+wNPCMovementDirections2:: ; cc97
+
+wSwitchPartyMonTempBuffer:: ; cc97
+; temporary buffer when swapping party mon data
+ ds 10
+
+wcca1:: ds 49
+
+wRLEByteCount:: ; ccd2
+ ds 1
+
+wSimulatedJoypadStatesEnd:: ; ccd3
+; this is the end of the joypad states
+; the list starts above this address and extends downwards in memory until here
+; overloaded with below labels
+
+wccd3:: ds 1
+wccd4:: ds 1
+
+; if [ccd5] != 1, the second AI layer is not applied
+wAILayer2Encouragement:: ; ccd5
+ ds 1
+ ds 1
+
+; current HP of player and enemy substitutes
+wPlayerSubstituteHP:: ; ccd7
+ ds 1
+wEnemySubstituteHP:: ; ccd8
+ ds 1
+
+wccd9:: ds 2
+
+wMoveMenuType:: ; ccdb
+; 0=regular, 1=mimic, 2=above message box (relearn, heal pp..)
+ ds 1
+
+wPlayerSelectedMove:: ; ccdc
+ ds 1
+wEnemySelectedMove:: ; ccdd
+ ds 1
+
+wLinkBattleRandomNumberListIndex:: ; ccde
+ ds 1
+
+wAICount:: ; ccdf
+; number of times remaining that AI action can occur
+ ds 1
+
+ ds 2
+
+wEnemyMoveListIndex:: ; cce2
+ ds 1
+
+wcce3:: ds 1
+wcce4:: ds 1
+
+wTotalPayDayMoney:: ; cce5
+; total amount of money made using Pay Day during the current battle
+ ds 3
+
+wSafariEscapeFactor:: ; cce8
+ ds 1
+wSafariBaitFactor:: ; cce9
+ ds 1;
+
+ ds 1
+
+wcceb:: ds 1
+wccec:: ds 1
+
+wMonIsDisobedient:: ds 1 ; cced
+
+wPlayerDisabledMoveNumber:: ds 1 ; ccee
+wEnemyDisabledMoveNumber:: ds 1 ; ccef
+
+wccf0:: ds 1
+
+wPlayerUsedMove:: ds 1 ; ccf1
+wEnemyUsedMove:: ds 1 ; ccf2
+
+wccf3:: ds 1
+
+wMoveDidntMiss:: ds 1 ; ccf4
+
+wPartyFoughtCurrentEnemyFlags:: ; ccf5
+; flags that indicate which party members have fought the current enemy mon
+ flag_array 6
+
+wccf6:: ds 1
+wccf7:: ds 14
+
+wUnknownSlotVar:: ; cd05
+
+wEnemyNumHits:: ; cd05
+; number of hits by enemy in attacks like Double Slap, etc.
+
+wEnemyBideAccumulatedDamage:: ; cd05
+; the amount of damage accumulated by the enemy while biding (2 bytes)
+
+ds 10
+
+wInGameTradeGiveMonSpecies:: ; cd0f
+
+wPlayerMonUnmodifiedLevel:: ; cd0f
+ ds 1
+
+wInGameTradeTextPointerTablePointer:: ; cd10
+
+wPlayerMonUnmodifiedMaxHP:: ; cd10
+ ds 2
+
+wInGameTradeTextPointerTableIndex:: ; cd12
+
+wPlayerMonUnmodifiedAttack:: ; cd12
+ ds 1
+wInGameTradeGiveMonName:: ; cd13
+ ds 1
+wPlayerMonUnmodifiedDefense:: ; cd14
+ ds 2
+wPlayerMonUnmodifiedSpeed:: ; cd16
+ ds 2
+wPlayerMonUnmodifiedSpecial:: ; cd18
+ ds 2
+
+; stat modifiers for the player's current pokemon
+; value can range from 1 - 13 ($1 to $D)
+; 7 is normal
+
+wPlayerMonStatMods::
+wPlayerMonAttackMod:: ; cd1a
+ ds 1
+wPlayerMonDefenseMod:: ; cd1b
+ ds 1
+wPlayerMonSpeedMod:: ; cd1c
+ ds 1
+wPlayerMonSpecialMod:: ; cd1d
+ ds 1
+
+wInGameTradeReceiveMonName:: ; cd1e
+
+wPlayerMonAccuracyMod:: ; cd1e
+ ds 1
+wPlayerMonEvasionMod:: ; cd1f
+ ds 1
+
+ ds 3
+
+wEnemyMonUnmodifiedLevel:: ; cd23
+ ds 1
+wEnemyMonUnmodifiedMaxHP:: ; cd24
+ ds 2
+wEnemyMonUnmodifiedAttack:: ; cd26
+ ds 2
+wEnemyMonUnmodifiedDefense:: ; cd28
+ ds 1
+
+wInGameTradeMonNick:: ; cd29
+ ds 1
+
+wEnemyMonUnmodifiedSpeed:: ; cd2a
+ ds 2
+wEnemyMonUnmodifiedSpecial:: ; cd2c
+ ds 1
+
+wEngagedTrainerClass:: ; cd2d
+ ds 1
+wEngagedTrainerSet:: ; cd2e
+; ds 1
+
+; stat modifiers for the enemy's current pokemon
+; value can range from 1 - 13 ($1 to $D)
+; 7 is normal
+
+wEnemyMonStatMods::
+wEnemyMonAttackMod:: ; cd2e
+ ds 1
+wEnemyMonDefenseMod:: ; cd2f
+ ds 1
+wEnemyMonSpeedMod:: ; cd30
+ ds 1
+wEnemyMonSpecialMod:: ; cd31
+ ds 1
+wEnemyMonAccuracyMod:: ; cd32
+ ds 1
+wEnemyMonEvasionMod:: ; cd33
+ ds 1
+
+wInGameTradeReceiveMonSpecies::
+ ds 1
+
+ ds 2
+
+wNPCMovementDirections2Index:: ; cd37
+
+wcd37:: ds 1
+
+wSimulatedJoypadStatesIndex:: ; cd38
+; the next simulated joypad state is at wSimulatedJoypadStatesEnd plus this value minus 1
+; 0 if the joypad state is not being simulated
+ ds 1
+
+wWastedByteCD39:: ; cd39
+; written to but nothing ever reads it
+ ds 1
+
+wWastedByteCD3A:: ; cd3a
+; written to but nothing ever reads it
+ ds 1
+
+wOverrideSimulatedJoypadStatesMask:: ; cd3b
+; mask indicating which real button presses can override simulated ones
+; XXX is it ever not 0?
+ ds 1
+
+ ds 1
+
+wTradedPlayerMonSpecies:: ; cd3d
+
+wTradingWhichPlayerMon:: ; cd3d
+
+wChangeBoxSavedMapTextPointer:: ; cd3d
+
+wFlyAnimUsingCoordList:: ; cd3d
+
+wPlayerSpinInPlaceAnimFrameDelay:: ; cd3d
+
+wPlayerSpinWhileMovingUpOrDownAnimDeltaY:: ; cd3d
+
+wHiddenObjectFunctionArgument:: ; cd3d
+
+wSubtrahend:: ; cd3d
+; subtract (BCD) wSubtrahend, wSubtrahend+1, wSubtrahend+2
+
+wWhichTrade:: ; cd3d
+; which entry from TradeMons to select
+
+wTrainerSpriteOffset:: ; cd3d
+ ds 1
+
+wTradedEnemyMonSpecies:: ; cd3e
+
+wTradingWhichEnemyMon:: ; cd3e
+
+wFlyAnimCounter:: ; cd3e
+
+wPlayerSpinInPlaceAnimFrameDelayDelta:: ; cd3e
+
+wPlayerSpinWhileMovingUpOrDownAnimMaxY:: ; cd3e
+
+wHiddenObjectFunctionRomBank:: ; cd3e
+
+wTrainerEngageDistance:: ; cd3e
+ ds 1
+
+wNameOfPlayerMonToBeTraded:: ; cd3f
+
+wFlyAnimBirdSpriteImageIndex:: ; cd3f
+
+wPlayerSpinInPlaceAnimFrameDelayEndValue:: ; cd3f
+
+wPlayerSpinWhileMovingUpOrDownAnimFrameDelay:: ; cd3f
+
+wHiddenObjectIndex:: ; cd3f
+
+wTrainerFacingDirection:: ; cd3f
+wcd3f::
+ ds 1
+
+wPlayerSpinInPlaceAnimSoundID:: ; cd40
+
+wHiddenObjectY:: ; cd40
+
+wTrainerScreenY:: ; cd40
+ ds 1
+
+wTradedPlayerMonOT:: ; cd41
+
+wHiddenObjectX:: ; cd41
+
+wTrainerScreenX:: ; cd41
+ ds 1
+
+wcd42:: ds 1
+wcd43:: ds 1
+wcd44:: ds 1
+wcd45:: ds 1
+wcd46:: ds 1
+wcd47:: ds 1
+wcd48:: ds 1
+wcd49:: ds 1
+wcd4a:: ds 1
+wcd4b:: ds 1
+
+wTradedPlayerMonOTID:: ; cd4c
+
+wcd4c:: ds 1
+wcd4d:: ds 1
+
+wTradedEnemyMonOT:: ; cd4e
+
+wcd4e:: ds 1
+wcd4f:: ds 1
+wcd50:: ds 9
+
+wTradedEnemyMonOTID:: ; cd59
+ ds 2
+
+wcd5b:: ds 1
+wcd5c:: ds 1
+
+wMonPartySpriteSpecies:: ; cd5d
+ ds 1
+
+wLeftGBMonSpecies:: ; cd5e
+; in the trade animation, the mon that leaves the left gameboy
+ ds 1
+
+wRightGBMonSpecies:: ; cd5f
+; in the trade animation, the mon that leaves the right gameboy
+ ds 1
+
+wFlags_0xcd60:: ; cd60
+; bit 0: is player engaged by trainer (to avoid being engaged by multiple trainers simultaneously)
+; bit 1: boulder dust animation (from using Strength) pending
+; bit 5: don't play sound when A or B is pressed in menu
+; bit 6: tried pushing against boulder once (you need to push twice before it will move)
+ ds 1
+
+ ds 9
+
+wcd6a:: ds 1
+
+wJoyIgnore:: ; cd6b
+; Set buttons are ignored.
+ ds 1
+
+wcd6c:: ds 1
+wcd6d:: ds 4
+wcd71:: ds 1
+wcd72:: ds 5
+wcd77:: ds 1
+wcd78:: ds 9
+
+wSerialOtherGameboyRandomNumberListBlock:: ; cd81
+; buffer for transferring the random number list generated by the other gameboy
+
+wTileMapBackup2:: ; cd81
+; second buffer for temporarily saving and restoring current screen's tiles (e.g. if menus are drawn on top)
+ ds 20 * 18
+
+wBuffer:: ; cee9
+; Temporary storage area of 30 bytes.
+wHPBarMaxHP:: ; cee9
+ ds 2
+wHPBarOldHP:: ; ceeb
+ ds 2
+wHPBarNewHP:: ; ceed
+ ds 2
+wHPBarDelta:: ; ceef
+ ds 1
+
+wcef0:: ds 1
+wcef1:: ds 12
+
+wHPBarHPDifference:: ; cefd
+ ds 1
+ ds 7
+
+wcf05:: ds 1
+wcf06:: ds 1
+
+wAnimSoundID:: ; cf07
+; sound ID during battle animations
+ ds 1
+
+wcf08:: ds 1
+wcf09:: ds 1
+wcf0a:: ds 1
+wBattleResult:: ; cf0b
+; $00 - win
+; $01 - lose
+; $02 - draw
+ ds 1
+
+wAutoTextBoxDrawingControl:: ; cf0c
+; bit 0: if set, DisplayTextID automatically draws a text box
+ ds 1
+
+wcf0d:: ds 1
+wcf0e:: ds 1
+wcf0f:: ds 1
+
+wNPCMovementScriptFunctionNum:: ; cf10
+; which script function within the pointer table indicated by
+; wNPCMovementScriptPointerTableNum
+ ds 1
+
+wcf11:: ds 1
+
+wPredefParentBank:: ; cf12
+ ds 1
+
+wSpriteIndex:: ds 1
+
+wCurSpriteMovement2:: ; cf14
+; movement byte 2 of current sprite
+ ds 1
+
+ ds 2
+
+wNPCMovementScriptSpriteOffset:: ; cf17
+; sprite offset of sprite being controlled by NPC movement script
+ ds 1
+
+wcf18:: ds 2
+
+wOnSGB:: ; cf1b
+; if running on SGB, it's 1, else it's 0
+ ds 1
+
+wcf1c:: ds 1
+wcf1d:: ds 1
+wcf1e:: ds 1
+wcf1f:: ds 6
+wcf25:: ds 8
+wcf2d:: ds 1
+wcf2e:: ds 2
+wcf30:: ds 7
+wcf37:: ds 20
+wcf4b:: ds 1
+wcf4c:: ds 1
+wGainBoostedExp:: ; cf4d
+ ds 1
+ ds 17
+
+wGymCityName:: ; cf5f
+wStringBuffer1:: ; cf5f
+ ds 16 + 1
+wGymLeaderName:: ; cf70
+wStringBuffer2:: ; cf70
+ ds 16 + 1
+wStringBuffer3:: ; cf81
+ ds 9 + 1
+
+wList:: ; cf8b
+ ds 2
+
+wcf8d:: ds 1
+wcf8e:: ds 1
+
+wItemPrices:: ; cf8f
+ ds 2
+
+wcf91:: ds 1
+
+wWhichPokemon:: ; cf92
+; which pokemon you selected
+ ds 1
+
+wcf93:: ds 1
+
+wHPBarType:: ; cf94
+; type of HP bar
+; $00 = enemy HUD in battle
+; $01 = player HUD in battle / status screen
+; $02 = party menu
+
+wListMenuID:: ; cf94
+; ID used by DisplayListMenuID
+ ds 1
+
+wcf95:: ds 1
+wcf96:: ds 1
+wcf97:: ds 1
+
+; LoadMonData copies mon data here
+wLoadedMon:: party_struct wLoadedMon ; cf98
+
+wFontLoaded:: ; cfc4
+; bit 0: The space in VRAM that is used to store walk animation tile patterns
+; for the player and NPCs is in use for font tile patterns.
+; This means that NPC movement must be disabled.
+; The other bits are unused.
+ ds 1
+
+wWalkCounter:: ; cfc5
+; walk animation counter
+ ds 1
+
+wTileInFrontOfPlayer:: ; cfc6
+; background tile number in front of the player (either 1 or 2 steps ahead)
+ ds 1
+
+wMusicHeaderPointer:: ; cfc7
+; (the current music channel address - $4000) / 3
+ ds 1
+
+wcfc8:: ds 1
+wcfc9:: ds 1
+wcfca:: ds 1
+
+wUpdateSpritesEnabled:: ; cfcb
+; $01 enables UpdateSprites; anything else disables it
+ ds 1
+
+W_ENEMYMOVENUM:: ; cfcc
+ ds 1
+W_ENEMYMOVEEFFECT:: ; cfcd
+ ds 1
+W_ENEMYMOVEPOWER:: ; cfce
+ ds 1
+W_ENEMYMOVETYPE:: ; cfcf
+ ds 1
+W_ENEMYMOVEACCURACY:: ; cfd0
+ ds 1
+W_ENEMYMOVEMAXPP:: ; cfd1
+ ds 1
+W_PLAYERMOVENUM:: ; cfd2
+ ds 1
+W_PLAYERMOVEEFFECT:: ; cfd3
+ ds 1
+W_PLAYERMOVEPOWER:: ; cfd4
+ ds 1
+W_PLAYERMOVETYPE:: ; cfd5
+ ds 1
+W_PLAYERMOVEACCURACY:: ; cfd6
+ ds 1
+W_PLAYERMOVEMAXPP:: ; cfd7
+ ds 1
+
+
+wEnemyMonSpecies2:: ; cfd8
+ ds 1
+wBattleMonSpecies2:: ; cfd9
+ ds 1
+
+wEnemyMonNick:: ds 11 ; cfda
+
+wEnemyMon:: ; cfe5
+; The wEnemyMon struct reaches past 0xcfff,
+; the end of wram bank 0 on cgb.
+; This has no significance on dmg, where wram
+; isn't banked (c000-dfff is contiguous).
+; However, recent versions of rgbds have replaced
+; dmg-style wram with cgb wram banks.
+
+; Until this is fixed, this struct will have
+; to be declared manually.
+
+wEnemyMonSpecies:: db
+wEnemyMonHP:: dw
+wEnemyMonPartyPos::
+wEnemyMonBoxLevel:: db
+wEnemyMonStatus:: db
+wEnemyMonType::
+wEnemyMonType1:: db
+wEnemyMonType2:: db
+wEnemyMonCatchRate_NotReferenced:: db
+wEnemyMonMoves:: ds NUM_MOVES
+wEnemyMonDVs:: ds 2
+wEnemyMonLevel:: db
+wEnemyMonMaxHP:: dw
+wEnemyMonAttack:: dw
+wEnemyMonDefense:: dw
+wEnemyMonSpeed:: dw
+wEnemyMonSpecial:: dw
+wEnemyMonPP:: ds 2 ; NUM_MOVES - 2
+SECTION "WRAM Bank 1", WRAMX, BANK[1]
+ ds 2 ; NUM_MOVES - 2
+
+wEnemyMonBaseStats:: ds 5
+wEnemyMonCatchRate:: ds 1
+wEnemyMonBaseExp:: ds 1
+
+wBattleMonNick:: ds 11 ; d009
+wBattleMon:: battle_struct wBattleMon ; d014
+
+
+W_TRAINERCLASS:: ; d031
+ ds 1
+
+ ds 1
+
+wTrainerPicPointer:: ; wd033
+ ds 2
+ ds 1
+wd036:: ds 16
+wd046:: ds 1
+wd047:: ds 1
+wd048:: ds 2
+
+W_TRAINERNAME:: ; d04a
+; 13 bytes for the letters of the opposing trainer
+; the name is terminated with $50 with possible
+; unused trailing letters
+ ds 13
+
+W_ISINBATTLE:: ; d057
+; no battle, this is 0
+; wild battle, this is 1
+; trainer battle, this is 2
+ ds 1
+
+wPartyGainExpFlags:: ; d058
+; flags that indicate which party members should be be given exp when GainExperience is called
+ flag_array 6
+
+W_CUROPPONENT:: ; d059
+; in a wild battle, this is the species of pokemon
+; in a trainer battle, this is the trainer class + $C8
+ ds 1
+
+W_BATTLETYPE:: ; d05a
+; in normal battle, this is 0
+; in old man battle, this is 1
+; in safari battle, this is 2
+ ds 1
+
+wDamageMultipliers:: ; d05b
+; bits 0-6: Effectiveness
+ ; $0 = immune
+ ; $5 = not very effective
+ ; $a = neutral
+ ; $14 = super-effective
+; bit 7: STAB
+ ds 1
+
+W_LONEATTACKNO:: ; d05c
+; which entry in LoneAttacks to use
+W_GYMLEADERNO:: ; d05c
+; it's actually the same thing as ^
+ ds 1
+W_TRAINERNO:: ; d05d
+; which instance of [youngster, lass, etc] is this?
+ ds 1
+
+wCriticalHitOrOHKO:: ; d05e
+; $00 = normal attack
+; $01 = critical hit
+; $02 = successful OHKO
+; $ff = failed OHKO
+ ds 1
+
+W_MOVEMISSED:: ; d05f
+ ds 1
+
+wPlayerStatsToDouble:: ; d060
+; always 0
+ ds 1
+
+wPlayerStatsToHalve:: ; d061
+; always 0
+ ds 1
+
+W_PLAYERBATTSTATUS1:: ; d062
+; bit 0 - bide
+; bit 1 - thrash / petal dance
+; bit 2 - attacking multiple times (e.g. double kick)
+; bit 3 - flinch
+; bit 4 - charging up for attack
+; bit 5 - using multi-turn move (e.g. wrap)
+; bit 6 - invulnerable to normal attack (using fly/dig)
+; bit 7 - confusion
+ ds 1
+
+W_PLAYERBATTSTATUS2:: ; d063
+; bit 0 - X Accuracy effect
+; bit 1 - protected by "mist"
+; bit 2 - focus energy effect
+; bit 4 - has a substitute
+; bit 5 - need to recharge
+; bit 6 - rage
+; bit 7 - leech seeded
+ ds 1
+
+W_PLAYERBATTSTATUS3:: ; d064
+; bit 0 - toxic
+; bit 1 - light screen
+; bit 2 - reflect
+; bit 3 - tranformed
+ ds 1
+
+wEnemyStatsToDouble:: ; d065
+; always 0
+ ds 1
+
+wEnemyStatsToHalve:: ; d066
+; always 0
+ ds 1
+
+W_ENEMYBATTSTATUS1:: ; d067
+ ds 1
+W_ENEMYBATTSTATUS2:: ; d068
+ ds 1
+W_ENEMYBATTSTATUS3:: ; d069
+ ds 1
+
+wPlayerNumAttacksLeft::
+; when the player is attacking multiple times, the number of attacks left
+ ds 1
+
+W_PLAYERCONFUSEDCOUNTER:: ; wd06b
+ ds 1
+
+W_PLAYERTOXICCOUNTER:: ; d06c
+ ds 1
+W_PLAYERDISABLEDMOVE:: ; d06d
+; high nibble: which move is disabled (1-4)
+; low nibble: disable turns left
+ ds 1
+
+ ds 1
+
+wEnemyNumAttacksLeft:: ; d06f
+; when the enemy is attacking multiple times, the number of attacks left
+ ds 1
+
+W_ENEMYCONFUSEDCOUNTER:: ; wd070
+ ds 1
+
+W_ENEMYTOXICCOUNTER:: ; d071
+ ds 1
+W_ENEMYDISABLEDMOVE:: ; d072
+; high nibble: which move is disabled (1-4)
+; low nibble: disable turns left
+ ds 1
+
+ ds 1
+
+wPlayerNumHits:: ; d074
+; number of hits by player in attacks like Double Slap, etc.
+
+wPlayerBideAccumulatedDamage:: ; d074
+; the amount of damage accumulated by the player while biding (2 bytes)
+
+wUnknownSerialCounter2:: ; d075
+; 2 bytes
+
+ ds 4
+
+wEscapedFromBattle::
+; non-zero when an item or move that allows escape from battle was used
+ ds 1
+
+wd079::
+wAmountMoneyWon:: ds 1 ; wd079 - wd07b
+wd07a:: ds 1
+ ds 1
+
+W_ANIMATIONID:: ; d07c
+; ID number of the current battle animation
+ ds 1
+
+wd07d:: ds 1
+wd07e:: ds 3
+
+; base coordinates of frame block
+W_BASECOORDX:: ; d081
+ ds 1
+W_BASECOORDY:: ; d082
+ ds 1
+
+; low health alarm counter/enable
+; high bit = enable, others = timer to cycle frequencies
+wLowHealthAlarm:: ds 1 ; d083
+
+W_FBTILECOUNTER:: ; d084
+; counts how many tiles of the current frame block have been drawn
+ ds 1
+
+wd085:: ds 1
+
+W_SUBANIMFRAMEDELAY:: ; d086
+; duration of each frame of the current subanimation in terms of screen refreshes
+ ds 1
+W_SUBANIMCOUNTER:: ; d087
+; counts the number of subentries left in the current subanimation
+ ds 1
+
+wd088:: ds 1
+
+W_NUMFBTILES:: ; d089
+; number of tiles in current battle animation frame block
+ ds 1
+
+wTradedMonMovingRight:: ; d08a
+; $01 if mon is moving from left gameboy to right gameboy; $00 if vice versa
+
+wd08a:: ds 1
+
+wTownMapSpriteBlinkingCounter:: ; d08b
+
+wPartyMonAnimCounter:: ; d08b
+
+W_SUBANIMTRANSFORM:: ; d08b
+; controls what transformations are applied to the subanimation
+; 01: flip horizontally and vertically
+; 02: flip horizontally and translate downwards 40 pixels
+; 03: translate base coordinates of frame blocks, but don't change their internal coordinates or flip their tiles
+; 04: reverse the subanimation
+ ds 1
+
+wEndBattleWinTextPointer:: ; d08c
+ ds 2
+
+wEndBattleLoseTextPointer:: ; d08e
+ ds 2
+
+ ds 2
+
+wEndBattleTextRomBank:: ; d092
+ ds 1
+
+ ds 1
+
+W_SUBANIMADDRPTR:: ; d094
+; the address _of the address_ of the current subanimation entry
+ ds 2
+W_SUBANIMSUBENTRYADDR:: ; d096
+; the address of the current subentry of the current subanimation
+ ds 2
+
+ ds 2
+
+wd09a:: ds 1
+
+wTownMapSpriteBlinkingEnabled:: ; d09b
+; non-zero when enabled. causes nest locations to blink on and off.
+; the town selection cursor will blink regardless of what this value is
+
+wd09b:: ds 1
+
+W_FBDESTADDR:: ; d09c
+; current destination address in OAM for frame blocks (big endian)
+ ds 2
+
+W_FBMODE:: ; d09e
+; controls how the frame blocks are put together to form frames
+; specifically, after finishing drawing the frame block, the frame block's mode determines what happens
+; 00: clean OAM buffer and delay
+; 02: move onto the next frame block with no delay and no cleaning OAM buffer
+; 03: delay, but don't clean OAM buffer
+; 04: delay, without cleaning OAM buffer, and do not advance [W_FBDESTADDR], so that the next frame block will overwrite this one
+; sprite data is written column by column, each byte contains 8 columns (one for ech bit)
+; for 2bpp sprites, pairs of two consecutive bytes (i.e. pairs of consecutive rows of sprite data)
+; contain the upper and lower bit of each of the 8 pixels, respectively
+ ds 1
+
+wNewTileBlockID:: ; d09f
+
+wd09f:: ds 1
+wd0a0:: ds 1
+
+W_SPRITECURPOSX:: ; d0a1
+ ds 1
+W_SPRITECURPOSY:: ; d0a2
+ ds 1
+W_SPRITEWITDH:: ; d0a3
+ ds 1
+W_SPRITEHEIGHT:: ; d0a4
+ ds 1
+W_SPRITEINPUTCURBYTE:: ; d0a5
+; current input byte
+ ds 1
+W_SPRITEINPUTBITCOUNTER:: ; d0a6
+; bit offset of last read input bit
+ ds 1
+
+W_SPRITEOUTPUTBITOFFSET:: ; d0a7; determines where in the output byte the two bits are placed. Each byte contains four columns (2bpp data)
+; 3 -> XX000000 1st column
+; 2 -> 00XX0000 2nd column
+; 1 -> 0000XX00 3rd column
+; 0 -> 000000XX 4th column
+ ds 1
+
+W_SPRITELOADFLAGS:: ; d0a8
+; bit 0 determines used buffer (0 -> $a188, 1 -> $a310)
+; bit 1 loading last sprite chunk? (there are at most 2 chunks per load operation)
+ ds 1
+W_SPRITEUNPACKMODE:: ; d0a9
+ ds 1
+W_SPRITEFLIPPED:: ; d0aa
+ ds 1
+
+W_SPRITEINPUTPTR:: ; d0ab
+; pointer to next input byte
+ ds 2
+W_SPRITEOUTPUTPTR:: ; d0ad
+; pointer to current output byte
+ ds 2
+W_SPRITEOUTPUTPTRCACHED:: ; d0af
+; used to revert pointer for different bit offsets
+ ds 2
+W_SPRITEDECODETABLE0PTR:: ; d0b1
+; pointer to differential decoding table (assuming initial value 0)
+ ds 2
+W_SPRITEDECODETABLE1PTR:: ; d0b3
+; pointer to differential decoding table (assuming initial value 1)
+ ds 2
+
+wd0b5:: ds 1
+
+wNameListType:: ; d0b6
+ ds 1
+
+wPredefBank:: ; d0b7
+ ds 1
+
+W_MONHEADER:: ; d0b8
+W_MONHDEXNUM:: ; d0b8
+ ds 1
+
+W_MONHBASESTATS:: ; d0b9
+W_MONHBASEHP:: ; d0b9
+ ds 1
+W_MONHBASEATTACK:: ; d0ba
+ ds 1
+W_MONHBASEDEFENSE:: ; d0bb
+ ds 1
+W_MONHBASESPEED:: ; d0bc
+ ds 1
+W_MONHBASESPECIAL:: ; d0bd
+ ds 1
+
+W_MONHTYPES:: ; d0be
+W_MONHTYPE1:: ; d0be
+ ds 1
+W_MONHTYPE2:: ; d0bf
+ ds 1
+
+W_MONHCATCHRATE:: ; d0c0
+ ds 1
+W_MONHBASEXP:: ; d0c1
+ ds 1
+W_MONHSPRITEDIM:: ; d0c2
+ ds 1
+W_MONHFRONTSPRITE:: ; d0c3
+ ds 2
+W_MONHBACKSPRITE:: ; d0c5
+ ds 2
+
+W_MONHMOVES:: ; d0c7
+ ds 4
+
+W_MONHGROWTHRATE:: ; d0cb
+ ds 1
+
+W_MONHLEARNSET:: ; d0cc
+; bit field
+ flag_array 50 + 5
+ ds 1
+
+wd0d4:: ds 3
+
+W_MONHPADDING:: ; d0d7
+
+
+W_DAMAGE:: ; d0d7
+ ds 2
+
+ds 2
+
+wRepelRemainingSteps:: ; wd0db
+ ds 1
+
+wMoves:: ; wd0dc
+; list of moves for FormatMovesString
+ ds 4
+
+wMoveNum:: ; d0e0
+ ds 1
+
+wMovesString:: ; d0e1
+ ds 56
+
+wd119:: ds 1
+
+wWalkBikeSurfStateCopy:: ; d11a
+; wWalkBikeSurfState is sometimes copied here, but it doesn't seem to be used for anything
+ ds 1
+
+wd11b:: ds 1
+wd11c:: ds 1
+wd11d:: ds 1
+wd11e:: ds 1
+wd11f:: ds 1
+
+wNumRunAttempts::
+; number of times the player has tried to run from battle
+ ds 1
+
+wd121:: ds 1
+wd122:: ds 2
+wd124:: ds 1
+
+wTextBoxID:: ; d125
+ ds 1
+
+wd126:: ds 1
+
+W_CURENEMYLVL:: ; d127
+ ds 1
+
+wd128:: ds 1
+wd129:: ds 1
+wd12a:: ds 1
+
+wLinkState:: ; d12b
+ ds 1
+
+wTwoOptionMenuID:: ds 1
+wd12d:: ds 1
+wd12e:: ds 1
+wd12f:: ds 1
+wd130:: ds 1
+wd131:: ds 1
+wd132:: ds 1
+wd133:: ds 6
+wd139:: ds 1
+
+wIgnoreInputCounter:: ; d13a
+; counts downward each frame
+; when it hits 0, bit 5 (ignore input bit) of wd730 is reset
+ ds 1
+
+wStepCounter:: ; d13b
+; counts down once every step
+ ds 1
+
+wNumberOfNoRandomBattleStepsLeft:: ; d13c
+; after a battle, you have at least 3 steps before a random battle can occur
+ ds 1
+
+W_PRIZE1:: ; d13d
+ ds 1
+W_PRIZE2:: ; d13e
+ ds 1
+W_PRIZE3:: ; d13f
+ ds 1
+
+ ds 1
+
+wSerialRandomNumberListBlock:: ; d141
+; the first 7 bytes are the preamble
+
+wd141:: ds 2
+wd143:: ds 2
+wd145:: ds 3
+
+wLinkBattleRandomNumberList:: ; d148
+; shared list of 9 random numbers, indexed by wLinkBattleRandomNumberListIndex
+ ds 10
+
+wSerialPlayerDataBlock:: ; d152
+; the first 6 bytes are the preamble
+
+wd152:: ds 1
+wd153:: ds 3
+wd156:: ds 1
+wd157:: ds 1
+
+
+wPlayerName:: ; d158
+ ds 11
+
+wPartyCount:: ds 1 ; d163
+wPartySpecies:: ds PARTY_LENGTH ; d164
+wPartyEnd:: ds 1 ; d16a
+
+wPartyMons::
+wPartyMon1:: party_struct wPartyMon1 ; d16b
+wPartyMon2:: party_struct wPartyMon2 ; d197
+wPartyMon3:: party_struct wPartyMon3 ; d1c3
+wPartyMon4:: party_struct wPartyMon4 ; d1ef
+wPartyMon5:: party_struct wPartyMon5 ; d21b
+wPartyMon6:: party_struct wPartyMon6 ; d247
+
+wPartyMonOT:: ds 11 * PARTY_LENGTH ; d273
+wPartyMonNicks:: ds 11 * PARTY_LENGTH ; d2b5
+
+
+wPokedexOwned:: ; d2f7
+ flag_array NUM_POKEMON
+wPokedexOwnedEnd::
+
+wPokedexSeen:: ; d30a
+ flag_array NUM_POKEMON
+wPokedexSeenEnd::
+
+
+wNumBagItems:: ; d31d
+ ds 1
+wBagItems:: ; d31e
+; item, quantity
+ ds 20 * 2
+ ds 1 ; end
+
+wPlayerMoney:: ; d347
+ ds 3 ; BCD
+
+W_RIVALNAME:: ; d34a
+ ds 11
+
+W_OPTIONS:: ; d355
+; bit 7 = battle animation
+; 0: On
+; 1: Off
+; bit 6 = battle style
+; 0: Shift
+; 1: Set
+; bits 0-3 = text speed (number of frames to delay after printing a letter)
+; 1: Fast
+; 3: Medium
+; 5: Slow
+ ds 1
+
+W_OBTAINEDBADGES:: ; d356
+ ds 1
+
+ ds 1
+
+wd358:: ds 1
+
+wPlayerID:: ; d359
+ ds 2
+
+wd35b:: ds 1
+wd35c:: ds 1
+
+wMapPalOffset:: ; d35d
+; offset subtracted from FadePal4 to get the background and object palettes for the current map
+; normally, it is 0. it is 6 when Flash is needed, causing FadePal2 to be used instead of FadePal4
+ ds 1
+
+W_CURMAP:: ; d35e
+ ds 1
+
+wCurrentTileBlockMapViewPointer:: ; d35f
+; pointer to the upper left corner of the current view in the tile block map
+ ds 2
+
+W_YCOORD:: ; d361
+; player’s position on the current map
+ ds 1
+
+W_XCOORD:: ; d362
+ ds 1
+
+W_YBLOCKCOORD:: ; d363
+; player's y position (by block)
+ ds 1
+
+W_XBLOCKCOORD:: ; d364
+ ds 1
+
+wLastMap:: ; d365
+ ds 1
+
+wd366:: ds 1
+
+W_CURMAPTILESET:: ; d367
+ ds 1
+
+W_CURMAPHEIGHT:: ; d368
+; blocks
+ ds 1
+
+W_CURMAPWIDTH:: ; d369
+; blocks
+ ds 1
+
+W_MAPDATAPTR:: ; d36a
+ ds 2
+
+W_MAPTEXTPTR:: ; d36c
+ ds 2
+
+W_MAPSCRIPTPTR:: ; d36e
+ ds 2
+
+W_MAPCONNECTIONS:: ; d370
+; connection byte
+ ds 1
+
+W_MAPCONN1PTR:: ; d371
+ ds 1
+
+wd372:: ds 1
+wd373:: ds 1
+wd374:: ds 1
+wd375:: ds 1
+wd376:: ds 1
+wd377:: ds 1
+wd378:: ds 1
+wd379:: ds 1
+wd37a:: ds 1
+wd37b:: ds 1
+
+W_MAPCONN2PTR:: ; d37c
+ ds 1
+
+wd37d:: ds 1
+wd37e:: ds 1
+wd37f:: ds 1
+wd380:: ds 1
+wd381:: ds 1
+wd382:: ds 1
+wd383:: ds 1
+wd384:: ds 1
+wd385:: ds 1
+wd386:: ds 1
+
+W_MAPCONN3PTR:: ; d387
+ ds 1
+
+wd388:: ds 1
+wd389:: ds 1
+wd38a:: ds 1
+wd38b:: ds 1
+wd38c:: ds 1
+wd38d:: ds 1
+wd38e:: ds 1
+wd38f:: ds 1
+wd390:: ds 1
+wd391:: ds 1
+
+W_MAPCONN4PTR:: ; d392
+ ds 1
+
+wd393:: ds 1
+wd394:: ds 1
+wd395:: ds 1
+wd396:: ds 1
+wd397:: ds 1
+wd398:: ds 1
+wd399:: ds 1
+wd39a:: ds 1
+wd39b:: ds 1
+wd39c:: ds 1
+
+W_SPRITESET:: ; d39d
+; sprite set for the current map (11 sprite picture ID's)
+ ds 11
+
+W_SPRITESETID:: ; d3a8
+; sprite set ID for the current map
+ ds 1
+
+wd3a9:: ds 1
+wd3aa:: ds 3
+wd3ad:: ds 1
+
+wNumberOfWarps:: ; d3ae
+; number of warps in current map
+ ds 1
+
+wWarpEntries:: ; d3af
+; current map warp entries
+ ds 128
+
+wDestinationWarpID:: ; d42f
+; if $ff, the player's coordinates are not updated when entering the map
+ ds 1
+
+wd430:: ds 1 ; d430
+wd431:: ds 1 ; d431
+
+ ds 3
+
+wd435:: ds 1
+wd436:: ds 1
+
+ ds 60
+
+wd472:: ds 1
+wd473:: ds 1
+
+ ds 61
+
+wd4b0:: ds 1
+wd4b1:: ds 32
+wd4d1:: ds 16
+
+W_NUMSPRITES:: ; d4e1
+; number of sprites on the current map
+ ds 1
+
+; these two variables track the X and Y offset in blocks from the last special warp used
+; they don't seem to be used for anything
+wYOffsetSinceLastSpecialWarp:: ; d4e2
+ ds 1
+wXOffsetSinceLastSpecialWarp:: ; d4e3
+ ds 1
+
+W_MAPSPRITEDATA:: ; d4e4
+; two bytes per sprite (movement byte 2, text ID)
+ ds 32
+
+W_MAPSPRITEEXTRADATA:: ; d504
+; two bytes per sprite (trainer class/item ID, trainer set ID)
+ ds 32
+
+wd524:: ds 1
+wd525:: ds 1
+
+wMapViewVRAMPointer:: ; d526
+; the address of the upper left corner of the visible portion of the BG tile map in VRAM
+ ds 2
+
+wd528:: ds 1
+wd529:: ds 1
+wd52a:: ds 1
+
+W_TILESETBANK:: ; d52b
+ ds 1
+
+W_TILESETBLOCKSPTR:: ; d52c
+; maps blocks (4x4 tiles) to tiles
+ ds 2
+
+W_TILESETGFXPTR:: ; d52e
+ ds 2
+
+W_TILESETCOLLISIONPTR:: ; d530
+; list of all walkable tiles
+ ds 2
+
+W_TILESETTALKINGOVERTILES:: ; d532
+ ds 3
+
+W_GRASSTILE:: ; d535
+ ds 1
+
+ ds 4
+
+wNumBoxItems:: ; d53a
+ ds 1
+wBoxItems:: ; d53b
+; item, quantity
+ ds 50 * 2
+ ds 1 ; end
+
+wd5a0:: ds 2
+wd5a2:: ds 1
+wd5a3:: ds 1
+
+wPlayerCoins:: ; d5a4
+ ds 2 ; BCD
+
+W_MISSABLEOBJECTFLAGS:: ; d5a6
+; bit array of missable objects. set = removed
+ ds 39
+
+wd5cd:: ds 1
+
+W_MISSABLEOBJECTLIST:: ; d5ce
+; each entry consists of 2 bytes
+; * the sprite ID (depending on the current map)
+; * the missable object index (global, used for W_MISSABLEOBJECTFLAGS)
+; terminated with $FF
+ ds 17 * 2
+
+W_GAMEPROGRESSFLAGS:: ; d5f0
+; $c8 bytes
+ ds 0
+
+W_OAKSLABCURSCRIPT:: ; d5f0
+ ds 1
+W_PALLETTOWNCURSCRIPT:: ; d5f1
+ ds 1
+ ds 1
+W_BLUESHOUSECURSCRIPT:: ; d5f3
+ ds 1
+W_VIRIDIANCITYCURSCRIPT:: ; d5f4
+ ds 1
+ ds 2
+W_PEWTERCITYCURSCRIPT:: ; d5f7
+ ds 1
+W_ROUTE3CURSCRIPT:: ; d5f8
+ ds 1
+W_ROUTE4CURSCRIPT:: ; d5f9
+ ds 1
+ ds 1
+W_VIRIDIANGYMCURSCRIPT:: ; d5fb
+ ds 1
+W_PEWTERGYMCURSCRIPT:: ; d5fc
+ ds 1
+W_CERULEANGYMCURSCRIPT:: ; d5fd
+ ds 1
+W_VERMILIONGYMCURSCRIPT:: ; d5fe
+ ds 1
+W_CELADONGYMCURSCRIPT:: ; d5ff
+ ds 1
+W_ROUTE6CURSCRIPT:: ; d600
+ ds 1
+W_ROUTE8CURSCRIPT:: ; d601
+ ds 1
+W_ROUTE24CURSCRIPT:: ; d602
+ ds 1
+W_ROUTE25CURSCRIPT:: ; d603
+ ds 1
+W_ROUTE9CURSCRIPT:: ; d604
+ ds 1
+W_ROUTE10CURSCRIPT:: ; d605
+ ds 1
+W_MTMOON1CURSCRIPT:: ; d606
+ ds 1
+W_MTMOON3CURSCRIPT:: ; d607
+ ds 1
+W_SSANNE8CURSCRIPT:: ; d608
+ ds 1
+W_SSANNE9CURSCRIPT:: ; d609
+ ds 1
+W_ROUTE22CURSCRIPT:: ; d60a
+ ds 1
+ ds 1
+W_REDSHOUSE2CURSCRIPT:: ; d60c
+ ds 1
+W_VIRIDIANMARKETCURSCRIPT:: ; d60d
+ ds 1
+W_ROUTE22GATECURSCRIPT:: ; d60e
+ ds 1
+W_CERULEANCITYCURSCRIPT:: ; d60f
+ ds 1
+ ds 7
+W_SSANNE5CURSCRIPT:: ; d617
+ ds 1
+W_VIRIDIANFORESTCURSCRIPT:: ; d618
+ ds 1
+W_MUSEUM1FCURSCRIPT:: ; d619
+ ds 1
+W_ROUTE13CURSCRIPT:: ; d61a
+ ds 1
+W_ROUTE14CURSCRIPT:: ; d61b
+ ds 1
+W_ROUTE17CURSCRIPT:: ; d61c
+ ds 1
+W_ROUTE19CURSCRIPT:: ; d61d
+ ds 1
+W_ROUTE21CURSCRIPT:: ; d61e
+ ds 1
+W_SAFARIZONEENTRANCECURSCRIPT:: ; d61f
+ ds 1
+W_ROCKTUNNEL2CURSCRIPT:: ; d620
+ ds 1
+W_ROCKTUNNEL1CURSCRIPT:: ; d621
+ ds 1
+ ds 1
+W_ROUTE11CURSCRIPT:: ; d623
+ ds 1
+W_ROUTE12CURSCRIPT:: ; d624
+ ds 1
+W_ROUTE15CURSCRIPT:: ; d625
+ ds 1
+W_ROUTE16CURSCRIPT:: ; d626
+ ds 1
+W_ROUTE18CURSCRIPT:: ; d627
+ ds 1
+W_ROUTE20CURSCRIPT:: ; d628
+ ds 1
+W_SSANNE10CURSCRIPT:: ; d629
+ ds 1
+W_VERMILIONCITYCURSCRIPT:: ; d62a
+ ds 1
+W_POKEMONTOWER2CURSCRIPT:: ; d62b
+ ds 1
+W_POKEMONTOWER3CURSCRIPT:: ; d62c
+ ds 1
+W_POKEMONTOWER4CURSCRIPT:: ; d62d
+ ds 1
+W_POKEMONTOWER5CURSCRIPT:: ; d62e
+ ds 1
+W_POKEMONTOWER6CURSCRIPT:: ; d62f
+ ds 1
+W_POKEMONTOWER7CURSCRIPT:: ; d630
+ ds 1
+W_ROCKETHIDEOUT1CURSCRIPT:: ; d631
+ ds 1
+W_ROCKETHIDEOUT2CURSCRIPT:: ; d632
+ ds 1
+W_ROCKETHIDEOUT3CURSCRIPT:: ; d633
+ ds 1
+W_ROCKETHIDEOUT4CURSCRIPT:: ; d634
+ ds 2
+W_ROUTE6GATECURSCRIPT:: ; d636
+ ds 1
+W_ROUTE8GATECURSCRIPT:: ; d637
+ ds 2
+W_CINNABARISLANDCURSCRIPT:: ; d639
+ ds 1
+W_MANSION1CURSCRIPT:: ; d63a
+ ds 2
+W_MANSION2CURSCRIPT:: ; d63c
+ ds 1
+W_MANSION3CURSCRIPT:: ; d63d
+ ds 1
+W_MANSION4CURSCRIPT:: ; d63e
+ ds 1
+W_VICTORYROAD2CURSCRIPT:: ; d63f
+ ds 1
+W_VICTORYROAD3CURSCRIPT:: ; d640
+ ds 2
+W_FIGHTINGDOJOCURSCRIPT:: ; d642
+ ds 1
+W_SILPHCO2CURSCRIPT:: ; d643
+ ds 1
+W_SILPHCO3CURSCRIPT:: ; d644
+ ds 1
+W_SILPHCO4CURSCRIPT:: ; d645
+ ds 1
+W_SILPHCO5CURSCRIPT:: ; d646
+ ds 1
+W_SILPHCO6CURSCRIPT:: ; d647
+ ds 1
+W_SILPHCO7CURSCRIPT:: ; d648
+ ds 1
+W_SILPHCO8CURSCRIPT:: ; d649
+ ds 1
+W_SILPHCO9CURSCRIPT:: ; d64a
+ ds 1
+W_HALLOFFAMEROOMCURSCRIPT:: ; d64b
+ ds 1
+W_GARYCURSCRIPT:: ; d64c
+ ds 1
+W_LORELEICURSCRIPT:: ; d64d
+ ds 1
+W_BRUNOCURSCRIPT:: ; d64e
+ ds 1
+W_AGATHACURSCRIPT:: ; d64f
+ ds 1
+W_UNKNOWNDUNGEON3CURSCRIPT:: ; d650
+ ds 1
+W_VICTORYROAD1CURSCRIPT:: ; d651
+ ds 1
+ ds 1
+W_LANCECURSCRIPT:: ; d653
+ ds 1
+ ds 4
+W_SILPHCO10CURSCRIPT:: ; d658
+ ds 1
+W_SILPHCO11CURSCRIPT:: ; d659
+ ds 1
+ ds 1
+W_FUCHSIAGYMCURSCRIPT:: ; d65b
+ ds 1
+W_SAFFRONGYMCURSCRIPT:: ; d65c
+ ds 1
+ ds 1
+W_CINNABARGYMCURSCRIPT:: ; d65e
+ ds 1
+W_CELADONGAMECORNERCURSCRIPT:: ; d65f
+ ds 1
+W_ROUTE16GATECURSCRIPT:: ; d660
+ ds 1
+W_BILLSHOUSECURSCRIPT:: ; d661
+ ds 1
+W_ROUTE5GATECURSCRIPT:: ; d662
+ ds 1
+W_POWERPLANTCURSCRIPT:: ; d663
+; overload
+ ds 0
+W_ROUTE7GATECURSCRIPT:: ; d663
+; overload
+ ds 1
+ ds 1
+W_SSANNE2CURSCRIPT:: ; d665
+ ds 1
+W_SEAFOAMISLANDS4CURSCRIPT:: ; d666
+ ds 1
+W_ROUTE23CURSCRIPT:: ; d667
+ ds 1
+W_SEAFOAMISLANDS5CURSCRIPT:: ; d668
+ ds 1
+W_ROUTE18GATECURSCRIPT:: ; d669
+ ds 1
+
+ ds 134
+
+wd6f0:: ds 14
+wd6fe:: ds 2
+
+wWalkBikeSurfState:: ; d700
+; $00 = walking
+; $01 = biking
+; $02 = surfing
+ ds 1
+
+ ds 10
+
+W_TOWNVISITEDFLAG:: ; d70b
+ flag_array 13
+
+wSafariSteps:: ; d70d
+; starts at 502
+ ds 2
+
+W_FOSSILITEM:: ; d70f
+; item given to cinnabar lab
+ ds 1
+
+W_FOSSILMON:: ; d710
+; mon that will result from the item
+ ds 1
+
+ ds 2
+
+W_ENEMYMONORTRAINERCLASS:: ; d713
+; trainer classes start at $c8
+ ds 1
+
+wPlayerJumpingYScreenCoordsIndex:: ; d714
+ ds 1
+
+W_RIVALSTARTER:: ; d715
+ ds 1
+
+ ds 1
+
+W_PLAYERSTARTER:: ; d717
+ ds 1
+
+wBoulderSpriteIndex:: ; d718
+; sprite index of the boulder the player is trying to push
+ ds 1
+
+wLastBlackoutMap:: ; d719
+ ds 1
+
+wDestinationMap:: ; d71a
+; destination map (for certain types of special warps, not ordinary walking)
+ ds 1
+
+wd71b:: ds 1
+
+wTileInFrontOfBoulderAndBoulderCollisionResult:: ; d71c
+; used to store the tile in front of the boulder when trying to push a boulder
+; also used to store the result of the collision check ($ff for a collision and $00 for no collision)
+ ds 1
+
+wDungeonWarpDestinationMap:: ; d71d
+; destination map for dungeon warps
+ ds 1
+
+wWhichDungeonWarp:: ; d71e
+; which dungeon warp within the source map was used
+ ds 1
+
+wd71f:: ds 9
+
+wd728::
+; bit 0: using Strength outside of battle
+ ds 1
+
+ ds 1
+
+wd72a:: ds 2
+
+wd72c:: ; d72c
+; bit 0: if not set, the 3 minimum steps between random battles have passed
+ ds 1
+
+wd72d:: ds 1
+wd72e:: ds 2
+
+wd730::
+; bit 0: NPC sprite being moved by script
+; bit 5: ignore joypad input
+; bit 6: print text with no delay between each letter
+; bit 7: set if joypad states are being simulated in the overworld
+ ds 1
+
+ ds 1
+
+wd732:: ; d732
+; bit 0: play time being counted
+; bit 1: remnant of debug mode? not set by the game code.
+; if it is set
+; 1. skips most of Prof. Oak's speech, and uses NINTEN as the player's name and SONY as the rival's name
+; 2. does not have the player start in floor two of the playyer's house (instead sending them to [wLastMap])
+; 3. allows wild battles to be avoided by holding down B
+; bit 2: the target warp is a fly warp (bit 3 set or blacked out) or a dungeon warp (bit 4 set)
+; bit 3: used warp pad, escape rope, dig, teleport, or fly, so the target warp is a "fly warp"
+; bit 4: jumped into hole (Pokemon Mansion, Seafoam Islands, Victory Road) or went down waterfall (Seafoam Islands), so the target warp is a "dungeon warp"
+; bit 5: currently being forced to ride bike (cycling road)
+; bit 6: map destination is [wLastBlackoutMap] (usually the last used pokemon center, but could be the player's house)
+ ds 1
+
+W_FLAGS_D733:: ; d733
+; bit 4: use variable [W_CURMAPSCRIPT] instead of the provided index for next frame's map script (used to start battle when talking to trainers)
+; bit 7: used fly out of battle
+ ds 1
+
+wd734:: ds 2
+
+wd736:: ; d736
+; bit 0: check if the player is standing on a door and make him walk down a step if so
+; bit 1: the player is currently stepping down from a door
+; bit 2: standing on a warp
+; bit 6: jumping down a ledge
+ ds 1
+
+wCompletedInGameTradeFlags:: ; d737
+ ds 2
+
+ ds 2
+
+wd73b:: ds 1
+wd73c:: ds 3
+
+wCardKeyDoorY:: ; d73f
+ ds 1
+
+wCardKeyDoorX:: ; d740
+ ds 1
+
+ ds 2
+
+wd743:: ds 1
+wd744:: ds 3
+wd747:: ds 3
+wd74a:: ds 1
+
+wd74b:: ; d74b
+; bit 0: Prof. Oak has lead the player to the north end of his lab
+; bit 1: Prof. Oak has asked the player to choose a pokemon
+; bit 2: the player and the rival have received their pokemon
+; bit 3: the player has battled the rival in Oak's lab
+; bit 4: Prof. Oak has given the player 5 pokeballs
+; bit 5: received pokedex
+ ds 1
+
+wd74c:: ds 2
+wd74e:: ds 3
+wd751:: ds 1
+wd752:: ds 2
+wd754:: ds 1
+wd755:: ds 5
+wd75a:: ds 1
+wd75b:: ds 3
+wd75e:: ds 1
+wd75f:: ds 5
+wd764:: ds 1
+wd765:: ds 1
+wd766:: ds 1
+wd767:: ds 1
+wd768:: ds 1
+wd769:: ds 3
+wd76c:: ds 5
+wd771:: ds 2
+wd773:: ds 4
+wd777:: ds 1
+wd778:: ds 4
+wd77c:: ds 1
+wd77d:: ds 1
+wd77e:: ds 5
+wd783:: ds 11
+wd78e:: ds 2
+wd790:: ds 2
+wd792:: ds 4
+wd796:: ds 2
+wd798:: ds 2
+wd79a:: ds 1
+wd79b:: ds 1
+wd79c:: ds 5
+wd7a1:: ds 2
+wd7a3:: ds 12
+wd7af:: ds 2
+wd7b1:: ds 2
+wd7b3:: ds 1
+wd7b4:: ds 5
+wd7b9:: ds 4
+wd7bd:: ds 2
+wd7bf:: ds 3
+wd7c2:: ds 1
+wd7c3:: ds 2
+wd7c5:: ds 1
+wd7c6:: ds 3
+wd7c9:: ds 4
+wd7cd:: ds 2
+wd7cf:: ds 2
+wd7d1:: ds 1
+wd7d2:: ds 1
+wd7d3:: ds 2
+wd7d5:: ds 1
+wd7d6:: ds 1
+wd7d7:: ds 1
+wd7d8:: ds 1
+wd7d9:: ds 2
+wd7db:: ds 2
+wd7dd:: ds 2
+wd7df:: ds 1
+wd7e0:: ds 1
+wd7e1:: ds 2
+wd7e3:: ds 2
+wd7e5:: ds 2
+wd7e7:: ds 1
+wd7e8:: ds 1
+wd7e9:: ds 2
+wd7eb:: ds 2
+wd7ed:: ds 1
+wd7ee:: ds 1
+wd7ef:: ds 1
+wd7f0:: ds 1
+wd7f1:: ds 1
+wd7f2:: ds 1
+wd7f3:: ds 2
+wd7f5:: ds 1
+wd7f6:: ds 9
+wd7ff:: ds 4
+wd803:: ds 2
+wd805:: ds 2
+wd807:: ds 2
+wd809:: ds 10
+wd813:: ds 2
+wd815:: ds 1
+wd816:: ds 1
+wd817:: ds 2
+wd819:: ds 2
+wd81b:: ds 10
+wd825:: ds 1
+wd826:: ds 1
+wd827:: ds 1
+wd828:: ds 1
+wd829:: ds 1
+wd82a:: ds 1
+wd82b:: ds 1
+wd82c:: ds 1
+wd82d:: ds 1
+wd82e:: ds 1
+wd82f:: ds 1
+wd830:: ds 1
+wd831:: ds 1
+wd832:: ds 1
+wd833:: ds 1
+wd834:: ds 1
+wd835:: ds 1
+wd836:: ds 1
+wd837:: ds 1
+wd838:: ds 15
+wd847:: ds 2
+wd849:: ds 2
+wd84b:: ds 12
+wd857:: ds 8
+wd85f:: ds 4
+wd863:: ds 1
+wd864:: ds 1
+wd865:: ds 1
+wd866:: ds 1
+wd867:: ds 2
+wd869:: ds 20
+wd87d:: ds 2
+wd87f:: ds 1
+wd880:: ds 1
+wd881:: ds 1
+wd882:: ds 5
+
+wLinkEnemyTrainerName:: ; d887
+; linked game's trainer name
+
+W_GRASSRATE:: ; d887
+ ds 1
+
+W_GRASSMONS:: ; d888
+ ds 20
+
+
+wEnemyPartyCount:: ds 1 ; d89c
+wEnemyPartyMons:: ds PARTY_LENGTH + 1 ; d89d
+
+wEnemyMons:: ; d8a4
+wEnemyMon1:: party_struct wEnemyMon1
+wEnemyMon2:: party_struct wEnemyMon2
+wEnemyMon3:: party_struct wEnemyMon3
+wEnemyMon4:: party_struct wEnemyMon4
+wEnemyMon5:: party_struct wEnemyMon5
+wEnemyMon6:: party_struct wEnemyMon6
+
+wEnemyMonOT:: ds 11 * PARTY_LENGTH ; d9ac
+wEnemyMonNicks:: ds 11 * PARTY_LENGTH ; d9ee
+
+
+W_TRAINERHEADERPTR:: ; da30
+ ds 2
+
+ ds 6
+
+wda38:: ds 1
+
+W_CURMAPSCRIPT:: ; da39
+; index of current map script, mostly used as index for function pointer array
+; mostly copied from map-specific map script pointer and wirtten back later
+ ds 1
+
+ ds 6
+
+W_PLAYTIMEHOURS:: ; da40
+ ds 2
+W_PLAYTIMEMINUTES:: ; da42
+ ds 2
+W_PLAYTIMESECONDS:: ; da44
+ ds 1
+W_PLAYTIMEFRAMES:: ; da45
+ ds 1
+
+wSafariZoneGameOver:: ; da46
+ ds 1
+
+W_NUMSAFARIBALLS:: ; da47
+ ds 1
+
+
+W_DAYCARE_IN_USE:: ; da48
+; 0 if no pokemon is in the daycare
+; 1 if pokemon is in the daycare
+ ds 1
+
+W_DAYCAREMONNAME:: ds 11 ; da49
+W_DAYCAREMONOT:: ds 11 ; da54
+
+wDayCareMon:: box_struct wDayCareMon ; da5f
+
+
+W_NUMINBOX:: ds 1 ; da80
+wBoxSpecies:: ds MONS_PER_BOX + 1
+
+wBoxMons::
+wBoxMon1:: box_struct wBoxMon1 ; da96
+wBoxMon2:: ds box_struct_length * (MONS_PER_BOX + -1) ; dab7
+
+wBoxMonOT:: ds 11 * MONS_PER_BOX ; dd2a
+wBoxMonNicks:: ds 11 * MONS_PER_BOX ; de06
+wBoxMonNicksEnd:: ; dee2
+
+
+SECTION "Stack", WRAMX[$dfff], BANK[1]
+wStack:: ; dfff
+ ds -$100
+
+
+INCLUDE "sram.asm"
diff --git a/yellow/bank3c/overworld.asm b/yellow/bank3c/overworld.asm index 7ecac223..30a50431 100644 --- a/yellow/bank3c/overworld.asm +++ b/yellow/bank3c/overworld.asm @@ -1,195 +1,243 @@ -SECTION "bank3c",ROMX[$401c],BANK[$3c] -_AdvancePlayerSprite:: ; f010c (3c:f010c) - ld a,[wSpriteStateData1 + 3] ; delta Y - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X - ld c,a - ld hl,wWalkCounter ; walking animation counter - dec [hl] - jr nz,.afterUpdateMapCoords -; if it's the end of the animation, update the player's map coordinates - ld a,[W_YCOORD] - add b - ld [W_YCOORD],a - ld a,[W_XCOORD] - add c - ld [W_XCOORD],a -.afterUpdateMapCoords - ld a,[wWalkCounter] ; walking animation counter - cp a,$07 - jp nz,.scrollBackgroundAndSprites -; if this is the first iteration of the animation - ld a,c - cp a,$01 - jr nz,.checkIfMovingWest -; moving east - ld a,[wMapViewVRAMPointer] - ld e,a - and a,$e0 - ld d,a - ld a,e - add a,$02 - and a,$1f - or d - ld [wMapViewVRAMPointer],a - jr .adjustXCoordWithinBlock -.checkIfMovingWest - cp a,$ff - jr nz,.checkIfMovingSouth -; moving west - ld a,[wMapViewVRAMPointer] - ld e,a - and a,$e0 - ld d,a - ld a,e - sub a,$02 - and a,$1f - or d - ld [wMapViewVRAMPointer],a - jr .adjustXCoordWithinBlock -.checkIfMovingSouth - ld a,b - cp a,$01 - jr nz,.checkIfMovingNorth -; moving south - ld a,[wMapViewVRAMPointer] - add a,$40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] - inc a - and a,$03 - or a,$98 - ld [wMapViewVRAMPointer + 1],a - jr .adjustXCoordWithinBlock -.checkIfMovingNorth - cp a,$ff - jr nz,.adjustXCoordWithinBlock -; moving north - ld a,[wMapViewVRAMPointer] - sub a,$40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] - dec a - and a,$03 - or a,$98 - ld [wMapViewVRAMPointer + 1],a -.adjustXCoordWithinBlock - ld a,c - and a - jr z,.pointlessJump ; mistake? -.pointlessJump - ld hl,W_XBLOCKCOORD - ld a,[hl] - add c - ld [hl],a - cp a,$02 - jr nz,.checkForMoveToWestBlock -; moved into the tile block to the east - xor a - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp - inc [hl] - ld de,wCurrentTileBlockMapViewPointer - call MoveTileBlockMapPointerEast - jr .updateMapView -.checkForMoveToWestBlock - cp a,$ff - jr nz,.adjustYCoordWithinBlock -; moved into the tile block to the west - ld a,$01 - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp - dec [hl] - ld de,wCurrentTileBlockMapViewPointer - call MoveTileBlockMapPointerWest - jr .updateMapView -.adjustYCoordWithinBlock - ld hl,W_YBLOCKCOORD - ld a,[hl] - add b - ld [hl],a - cp a,$02 - jr nz,.checkForMoveToNorthBlock -; moved into the tile block to the south - xor a - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp - inc [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[W_CURMAPWIDTH] - call MoveTileBlockMapPointerSouth - jr .updateMapView -.checkForMoveToNorthBlock - cp a,$ff - jr nz,.updateMapView -; moved into the tile block to the north - ld a,$01 - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp - dec [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[W_CURMAPWIDTH] - call MoveTileBlockMapPointerNorth -.updateMapView - call LoadCurrentMapView - ld a,[wSpriteStateData1 + 3] ; delta Y - cp a,$01 - jr nz,.checkIfMovingNorth2 -; if moving south - call ScheduleSouthRowRedraw - jr .scrollBackgroundAndSprites -.checkIfMovingNorth2 - cp a,$ff - jr nz,.checkIfMovingEast2 -; if moving north - call ScheduleNorthRowRedraw - jr .scrollBackgroundAndSprites -.checkIfMovingEast2 - ld a,[wSpriteStateData1 + 5] ; delta X - cp a,$01 - jr nz,.checkIfMovingWest2 -; if moving east - call ScheduleEastColumnRedraw - jr .scrollBackgroundAndSprites -.checkIfMovingWest2 - cp a,$ff - jr nz,.scrollBackgroundAndSprites -; if moving west - call ScheduleWestColumnRedraw -.scrollBackgroundAndSprites - ld a,[wSpriteStateData1 + 3] ; delta Y - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X - ld c,a - sla b - sla c - ld a,[hSCY] - add b - ld [hSCY],a ; update background scroll Y - ld a,[hSCX] - add c - ld [hSCX],a ; update background scroll X -; shift all the sprites in the direction opposite of the player's motion -; so that the player appears to move relative to them - ld hl,wSpriteStateData1 + $14 - ld a,[W_NUMSPRITES] ; number of sprites - and a ; are there any sprites? - jr z,.done - ld e,a -.spriteShiftLoop - ld a,[hl] - sub b - ld [hli],a - inc l - ld a,[hl] - sub c - ld [hl],a - ld a,$0e - add l - ld l,a - dec e - jr nz,.spriteShiftLoop -.done - ret +SECTION "bank3c",ROMX[$410c],BANK[$3c]
+_AdvancePlayerSprite:: ; f010c (3c:410c)
+ ld a,[wSpriteStateData1 + 3] ; delta Y
+ ld b,a
+ ld a,[wSpriteStateData1 + 5] ; delta X
+ ld c,a
+ ld hl,wWalkCounter ; walking animation counter
+ dec [hl]
+ jr nz,.afterUpdateMapCoords
+; if it's the end of the animation, update the player's map coordinates
+ ld a,[W_YCOORD]
+ add b
+ ld [W_YCOORD],a
+ ld a,[W_XCOORD]
+ add c
+ ld [W_XCOORD],a
+.afterUpdateMapCoords
+ ld a,[wWalkCounter] ; walking animation counter
+ cp a,$07
+ jp nz,.scrollBackgroundAndSprites
+; if this is the first iteration of the animation
+ ld a,c
+ cp a,$01
+ jr nz,.checkIfMovingWest
+; moving east
+ ld a,[wMapViewVRAMPointer]
+ ld e,a
+ and a,$e0
+ ld d,a
+ ld a,e
+ add a,$02
+ and a,$1f
+ or d
+ ld [wMapViewVRAMPointer],a
+ jr .adjustXCoordWithinBlock
+.checkIfMovingWest
+ cp a,$ff
+ jr nz,.checkIfMovingSouth
+; moving west
+ ld a,[wMapViewVRAMPointer]
+ ld e,a
+ and a,$e0
+ ld d,a
+ ld a,e
+ sub a,$02
+ and a,$1f
+ or d
+ ld [wMapViewVRAMPointer],a
+ jr .adjustXCoordWithinBlock
+.checkIfMovingSouth
+ ld a,b
+ cp a,$01
+ jr nz,.checkIfMovingNorth
+; moving south
+ ld a,[wMapViewVRAMPointer]
+ add a,$40
+ ld [wMapViewVRAMPointer],a
+ jr nc,.adjustXCoordWithinBlock
+ ld a,[wMapViewVRAMPointer + 1]
+ inc a
+ and a,$03
+ or a,$98
+ ld [wMapViewVRAMPointer + 1],a
+ jr .adjustXCoordWithinBlock
+.checkIfMovingNorth
+ cp a,$ff
+ jr nz,.adjustXCoordWithinBlock
+; moving north
+ ld a,[wMapViewVRAMPointer]
+ sub a,$40
+ ld [wMapViewVRAMPointer],a
+ jr nc,.adjustXCoordWithinBlock
+ ld a,[wMapViewVRAMPointer + 1]
+ dec a
+ and a,$03
+ or a,$98
+ ld [wMapViewVRAMPointer + 1],a
+.adjustXCoordWithinBlock
+ ld a,c
+ and a
+ jr z,.pointlessJump ; mistake?
+.pointlessJump
+ ld hl,W_XBLOCKCOORD
+ ld a,[hl]
+ add c
+ ld [hl],a
+ cp a,$02
+ jr nz,.checkForMoveToWestBlock
+; moved into the tile block to the east
+ xor a
+ ld [hl],a
+ ld hl,wXOffsetSinceLastSpecialWarp
+ inc [hl]
+ ld de,wCurrentTileBlockMapViewPointer
+ call MoveTileBlockMapPointerEast
+ jr .updateMapView
+.checkForMoveToWestBlock
+ cp a,$ff
+ jr nz,.adjustYCoordWithinBlock
+; moved into the tile block to the west
+ ld a,$01
+ ld [hl],a
+ ld hl,wXOffsetSinceLastSpecialWarp
+ dec [hl]
+ ld de,wCurrentTileBlockMapViewPointer
+ call MoveTileBlockMapPointerWest
+ jr .updateMapView
+.adjustYCoordWithinBlock
+ ld hl,W_YBLOCKCOORD
+ ld a,[hl]
+ add b
+ ld [hl],a
+ cp a,$02
+ jr nz,.checkForMoveToNorthBlock
+; moved into the tile block to the south
+ xor a
+ ld [hl],a
+ ld hl,wYOffsetSinceLastSpecialWarp
+ inc [hl]
+ ld de,wCurrentTileBlockMapViewPointer
+ ld a,[W_CURMAPWIDTH]
+ call MoveTileBlockMapPointerSouth
+ jr .updateMapView
+.checkForMoveToNorthBlock
+ cp a,$ff
+ jr nz,.updateMapView
+; moved into the tile block to the north
+ ld a,$01
+ ld [hl],a
+ ld hl,wYOffsetSinceLastSpecialWarp
+ dec [hl]
+ ld de,wCurrentTileBlockMapViewPointer
+ ld a,[W_CURMAPWIDTH]
+ call MoveTileBlockMapPointerNorth
+.updateMapView
+ call LoadCurrentMapView
+ ld a,[wSpriteStateData1 + 3] ; delta Y
+ cp a,$01
+ jr nz,.checkIfMovingNorth2
+; if moving south
+ call ScheduleSouthRowRedraw
+ jr .scrollBackgroundAndSprites
+.checkIfMovingNorth2
+ cp a,$ff
+ jr nz,.checkIfMovingEast2
+; if moving north
+ call ScheduleNorthRowRedraw
+ jr .scrollBackgroundAndSprites
+.checkIfMovingEast2
+ ld a,[wSpriteStateData1 + 5] ; delta X
+ cp a,$01
+ jr nz,.checkIfMovingWest2
+; if moving east
+ call ScheduleEastColumnRedraw
+ jr .scrollBackgroundAndSprites
+.checkIfMovingWest2
+ cp a,$ff
+ jr nz,.scrollBackgroundAndSprites
+; if moving west
+ call ScheduleWestColumnRedraw
+.scrollBackgroundAndSprites
+ ld a,[wSpriteStateData1 + 3] ; delta Y
+ ld b,a
+ ld a,[wSpriteStateData1 + 5] ; delta X
+ ld c,a
+ sla b
+ sla c
+ ld a,[hSCY]
+ add b
+ ld [hSCY],a ; update background scroll Y
+ ld a,[hSCX]
+ add c
+ ld [hSCX],a ; update background scroll X
+; shift all the sprites in the direction opposite of the player's motion
+; so that the player appears to move relative to them
+ ld hl,wSpriteStateData1 + $14
+ ld a,[W_NUMSPRITES] ; number of sprites
+ and a ; are there any sprites?
+ jr z,.done
+ ld e,a
+.spriteShiftLoop
+ ld a,[hl]
+ sub b
+ ld [hli],a
+ inc l
+ ld a,[hl]
+ sub c
+ ld [hl],a
+ ld a,$0e
+ add l
+ ld l,a
+ dec e
+ jr nz,.spriteShiftLoop
+.done
+ ret
+
+MoveTileBlockMapPointerEast:: ; 0e65 (0:0e65)
+ ld a,[de]
+ add a,$01
+ ld [de],a
+ ret nc
+ inc de
+ ld a,[de]
+ inc a
+ ld [de],a
+ ret
+
+MoveTileBlockMapPointerWest:: ; 0e6f (0:0e6f)
+ ld a,[de]
+ sub a,$01
+ ld [de],a
+ ret nc
+ inc de
+ ld a,[de]
+ dec a
+ ld [de],a
+ ret
+
+MoveTileBlockMapPointerSouth:: ; 0e79 (0:0e79)
+ add a,$06
+ ld b,a
+ ld a,[de]
+ add b
+ ld [de],a
+ ret nc
+ inc de
+ ld a,[de]
+ inc a
+ ld [de],a
+ ret
+
+MoveTileBlockMapPointerNorth:: ; 0e85 (0:0e85)
+ add a,$06
+ ld b,a
+ ld a,[de]
+ sub b
+ ld [de],a
+ ret nc
+ inc de
+ ld a,[de]
+ dec a
+ ld [de],a
+ ret
\ No newline at end of file diff --git a/yellow/bank3d/random.asm b/yellow/bank3d/random.asm index b7fb0edd..c7245c3e 100644 --- a/yellow/bank3d/random.asm +++ b/yellow/bank3d/random.asm @@ -1,15 +1,15 @@ -SECTION "bank3d",ROMX[$67DC],BANK[$3D] - -Random_:: -; Generate a random 16-bit value. - ld a, [rDIV] - ld b, a - ld a, [hRandomAdd] - adc b - ld [hRandomAdd], a - ld a, [rDIV] - ld b, a - ld a, [hRandomSub] - sbc b - ld [hRandomSub], a - ret +SECTION "bank3d",ROMX[$67DC],BANK[$3D]
+
+Random_::
+; Generate a random 16-bit value.
+ ld a, [rDIV]
+ ld b, a
+ ld a, [hRandomAdd]
+ adc b
+ ld [hRandomAdd], a
+ ld a, [rDIV]
+ ld b, a
+ ld a, [hRandomSub]
+ sbc b
+ ld [hRandomSub], a
+ ret
diff --git a/yellow/bank3f/main.asm b/yellow/bank3f/main.asm index ff2aa7a0..736ac8ae 100644 --- a/yellow/bank3f/main.asm +++ b/yellow/bank3f/main.asm @@ -1,11 +1,11 @@ -; asm to be added - -Func_fc5fa:: ; fc5fa (3f:45fa) - -Func_fc65b:: ; fc65b (3f:465b) - -Func_fc69a:: ; fc69a (3f:469a) - -Func_fcc08:: ; fcc08 (3f:4c08) - -Func_fcf0c:: ; fcf0c (3f:4f0c) +; asm to be added
+
+Func_fc5fa:: ; fc5fa (3f:45fa)
+
+Func_fc65b:: ; fc65b (3f:465b)
+
+Func_fc69a:: ; fc69a (3f:469a)
+
+Func_fcc08:: ; fcc08 (3f:4c08)
+
+Func_fcf0c:: ; fcf0c (3f:4f0c)
|