diff options
Diffstat (limited to 'engine/pikachu')
-rwxr-xr-x | engine/pikachu/pikachu_emotions.asm | 422 | ||||
-rwxr-xr-x | engine/pikachu/pikachu_follow.asm | 1578 | ||||
-rwxr-xr-x | engine/pikachu/pikachu_movement.asm | 1048 | ||||
-rwxr-xr-x | engine/pikachu/pikachu_pcm.asm | 154 | ||||
-rwxr-xr-x | engine/pikachu/pikachu_pic_animation.asm | 855 | ||||
-rwxr-xr-x | engine/pikachu/pikachu_status.asm | 258 | ||||
-rw-r--r-- | engine/pikachu/respawn_overworld_pikachu.asm | 6 |
7 files changed, 4321 insertions, 0 deletions
diff --git a/engine/pikachu/pikachu_emotions.asm b/engine/pikachu/pikachu_emotions.asm new file mode 100755 index 00000000..1378d383 --- /dev/null +++ b/engine/pikachu/pikachu_emotions.asm @@ -0,0 +1,422 @@ +IsPlayerTalkingToPikachu:: + ld a, [wd436] + and a + ret z + ldh a, [hSpriteIndexOrTextID] + cp $f + ret nz + call InitializePikachuTextID + xor a + ldh [hSpriteIndexOrTextID], a + ld [wd436], a + ret + +InitializePikachuTextID:: + ld a, TEXT_PIKACHU_ANIM ; display + ldh [hSpriteIndexOrTextID], a + xor a + ld [wPlayerMovingDirection], a + ld a, $1 + ld [wAutoTextBoxDrawingControl], a + call DisplayTextID + xor a + ld [wAutoTextBoxDrawingControl], a + ret + +DoStarterPikachuEmotions: + ld e, a + ld d, 0 + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] +.loop + ld a, [de] + inc de + cp $ff + jr z, .done + ld c, a + ld b, 0 + ld hl, StarterPikachuEmotionsJumptable + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + call JumpToAddress + jr .loop + +.done + ret + +StarterPikachuEmotionsJumptable: + dw StarterPikachuEmotionCommand_nop ; 0 + dw StarterPikachuEmotionCommand_text ; 1 + dw StarterPikachuEmotionCommand_pcm ; 2 + dw StarterPikachuEmotionCommand_emote ; 3 + dw StarterPikachuEmotionCommand_movement ; 4 + dw StarterPikachuEmotionCommand_pikapic ; 5 + dw StarterPikachuEmotionCommand_subcmd ; 6 + dw StarterPikachuEmotionCommand_delay ; 7 + dw StarterPikachuEmotionCommand_nop2 ; 8 + dw StarterPikachuEmotionCommand_9 ; 9 + dw StarterPikachuEmotionCommand_nop3 ; a + +StarterPikachuEmotionCommand_nop: +StarterPikachuEmotionCommand_nop3: + ret + +StarterPikachuEmotionCommand_text: + ld a, [de] + ld l, a + inc de + ld a, [de] + ld h, a + inc de + push de + call PrintText + pop de + ret + +StarterPikachuEmotionCommand_pcm: + ld a, [de] + inc de + push de + ld e, a + nop + call PlayPikachuSoundClip_ + pop de + ret + +PlayPikachuSoundClip_: + cp $ff + ret z + callfar PlayPikachuSoundClip + ret + +StarterPikachuEmotionCommand_emote: + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, [de] + inc de + push de + call ShowPikachuEmoteBubble + pop de + pop af + ld [wUpdateSpritesEnabled], a + ret + +ShowPikachuEmoteBubble: + ld [wWhichEmotionBubble], a + ld a, $f ; Pikachu + ld [wEmotionBubbleSpriteIndex], a + predef EmotionBubble + ret + +StarterPikachuEmotionCommand_movement: + ld a, [de] + inc de + ld l, a + ld a, [de] + inc de + ld h, a + push de + ld b, BANK(DoStarterPikachuEmotions) + call ApplyPikachuMovementData_ + pop de + ret + +StarterPikachuEmotionCommand_delay: + ld a, [de] + inc de + push de + ld c, a + call DelayFrames + pop de + ret + +StarterPikachuEmotionCommand_subcmd: + ld a, [de] + inc de + push de + ld e, a + ld d, 0 + ld hl, .Subcommands + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call JumpToAddress + pop de + ret + +.Subcommands: + dw LoadPikachuSpriteIntoVRAM + dw LoadFontTilePatterns + dw Pikachu_LoadCurrentMapViewUpdateSpritesAndDelay3 + dw WaitForTextScrollButtonPress + dw PikachuPewterPokecenterCheck + dw PikachuFanClubCheck + dw PikachuBillsHouseCheck + +StarterPikachuEmotionCommand_nop2: + ret + +StarterPikachuEmotionCommand_9: + push de + call StarterPikachuEmotionCommand_turnawayfromplayer + call UpdateSprites + pop de + ret + +StarterPikachuEmotionCommand_turnawayfromplayer: + ld a, [wSpritePlayerStateData1FacingDirection] + xor $4 + ld [wSpritePikachuStateData1FacingDirection], a + ret + +DeletedFunction_fcffb: +; Inexplicably empty. +REPT 5 + nop +ENDR + ret + +PlaySpecificPikachuEmotion: + ld a, e + jr load_expression + +TalkToPikachu:: + call MapSpecificPikachuExpression + jr c, load_expression + call GetPikaPicAnimationScriptIndex + call DeletedFunction_fcffb +load_expression: + ld [wExpressionNumber], a + ld hl, PikachuEmotionTable + call DoStarterPikachuEmotions + ret + +pikaemotion_def: MACRO +\1_id: + dw \1 +ENDM + +PikachuEmotionTable: + pikaemotion_def PikachuEmotion0 + pikaemotion_def PikachuEmotion1 + pikaemotion_def PikachuEmotion2 + pikaemotion_def PikachuEmotion3 + pikaemotion_def PikachuEmotion4 + pikaemotion_def PikachuEmotion5 + pikaemotion_def PikachuEmotion6 + pikaemotion_def PikachuEmotion7 + pikaemotion_def PikachuEmotion8 + pikaemotion_def PikachuEmotion9 + pikaemotion_def PikachuEmotion10 + pikaemotion_def PikachuEmotion11 + pikaemotion_def PikachuEmotion12 + pikaemotion_def PikachuEmotion13 + pikaemotion_def PikachuEmotion14 + pikaemotion_def PikachuEmotion15 + pikaemotion_def PikachuEmotion16 + pikaemotion_def PikachuEmotion17 + pikaemotion_def PikachuEmotion18 + pikaemotion_def PikachuEmotion19 + pikaemotion_def PikachuEmotion20 + pikaemotion_def PikachuEmotion21 ; used a fishing rod + pikaemotion_def PikachuEmotion22 + pikaemotion_def PikachuEmotion23 + pikaemotion_def PikachuEmotion24 + pikaemotion_def PikachuEmotion25 + pikaemotion_def PikachuEmotion26 ; wake up pikachu in pewter pokemon center + pikaemotion_def PikachuEmotion27 + pikaemotion_def PikachuEmotion28 + pikaemotion_def PikachuEmotion29 + pikaemotion_def PikachuEmotion30 + pikaemotion_def PikachuEmotion31 + pikaemotion_def PikachuEmotion32 + pikaemotion_def PikachuEmotion33 + +PikachuEmotion33: + db $ff + +MapSpecificPikachuExpression: + ld a, [wCurMap] + cp POKEMON_FAN_CLUB + jr nz, .notFanClub + ld hl, wd492 + bit 7, [hl] + ldpikaemotion a, PikachuEmotion29 + jr z, .play_emotion + call CheckPikachuFollowingPlayer + ldpikaemotion a, PikachuEmotion30 + jr nz, .play_emotion + jr .check_pikachu_status + +.notFanClub + ld a, [wCurMap] + cp PEWTER_POKECENTER + jr nz, .notPewterPokecenter + call CheckPikachuFollowingPlayer + ldpikaemotion a, PikachuEmotion26 + jr nz, .play_emotion + jr .check_pikachu_status + +.notPewterPokecenter + callfar Func_f24ae + ld a, e + cp $ff + jr nz, .play_emotion + jr .check_pikachu_status ; useless + +.check_pikachu_status + call IsPlayerPikachuAsleepInParty + ldpikaemotion a, PikachuEmotion11 + jr c, .play_emotion + callfar CheckPikachuFaintedOrStatused ; same bank + ldpikaemotion a, PikachuEmotion28 + jr c, .play_emotion + ld a, [wCurMap] + cp POKEMON_TOWER_1F + jr c, .notInLavenderTower + cp POKEMON_TOWER_7F + 1 + ldpikaemotion a, PikachuEmotion22 + jr c, .play_emotion +.notInLavenderTower + ld a, [wd49c] + and a + jr z, .mood_based_emotion + dec a + ld c, a + ld b, $0 + ld hl, .Emotions + add hl, bc + ld a, [hl] + jr .play_emotion + +.mood_based_emotion + and a + ret + +.play_emotion + scf + ret + +.Emotions: + dpikaemotion PikachuEmotion18 + dpikaemotion PikachuEmotion21 + dpikaemotion PikachuEmotion23 + dpikaemotion PikachuEmotion24 + dpikaemotion PikachuEmotion25 + +IsPlayerPikachuAsleepInParty: + xor a + ld [wWhichPokemon], a +.loop + ld a, [wWhichPokemon] + ld c, a + ld b, 0 + ld hl, wPartySpecies + add hl, bc + ld a, [hl] + cp $ff + jr z, .done + cp PIKACHU + jr nz, .curMonNotStarterPikachu + callfar IsThisPartymonStarterPikachu + jr nc, .curMonNotStarterPikachu + ld a, [wWhichPokemon] + ld hl, wPartyMon1Status + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hl] + and SLP + jr z, .done + jr .curMonSleepingPikachu + +.curMonNotStarterPikachu + ld a, [wWhichPokemon] + cp PARTY_LENGTH - 1 + jr z, .done + inc a + ld [wWhichPokemon], a + jr .loop + +.curMonSleepingPikachu + scf + ret + +.done + and a + ret + +INCLUDE "data/pikachu/pikachu_emotions.asm" + +PikachuWalksToNurseJoy: + ld a, $40 + ldh [hFFFC], a + call LoadPikachuSpriteIntoVRAM + call .GetMovementData + and a + jr z, .skip + call ApplyPikachuMovementData +.skip + xor a + ldh [hFFFC], a + ret + +.GetMovementData: + ld a, [wSpritePikachuStateData2MapY] + ld e, a + ld a, [wSpritePikachuStateData2MapX] + ld d, a + ld a, [wYCoord] + add 4 + cp e + jr z, .pikachu_at_same_y_as_player + jr nc, .pikachu_above_player + ld hl, .PikaMovementData1 + ld a, 1 + ret + +.pikachu_above_player + xor a + ret + +.pikachu_at_same_y_as_player + ld a, [wXCoord] + add 4 + cp d + jr c, .pikachu_to_right_of_player + ld hl, .PikaMovementData2 + ld a, 2 + ret + +.pikachu_to_right_of_player + ld hl, .PikaMovementData3 + ld a, 3 + ret + +.PikaMovementData1: + db $00 ; init + db $36 ; look up + db $2b ; walk up left + db $34 ; hop up right + db $3f ; ret + +.PikaMovementData2: + db $00 ; init + db $36 ; look up + db $34 ; hop up right + db $3f ; ret + +.PikaMovementData3: + db $00 ; init + db $36 ; look up + db $33 ; hop up left + db $3f ; ret diff --git a/engine/pikachu/pikachu_follow.asm b/engine/pikachu/pikachu_follow.asm new file mode 100755 index 00000000..9575c341 --- /dev/null +++ b/engine/pikachu/pikachu_follow.asm @@ -0,0 +1,1578 @@ +ShouldPikachuSpawn:: +; possibly to test if pika should be out? + ld a, [wPikachuOverworldStateFlags] + bit 5, a + jr nz, .hide + ld a, [wPikachuOverworldStateFlags] + bit 7, a + jr nz, .hide + call IsStarterPikachuInOurParty + jr nc, .hide + ld a, [wWalkBikeSurfState] + and a + jr nz, .hide + scf + ret + +.hide + and a + ret + +SchedulePikachuSpawnForAfterText:: + ld hl, wPikachuOverworldStateFlags + bit 4, [hl] + res 4, [hl] + jr nz, .normal_spawn_state + call EnablePikachuFollowingPlayer + call ClearPikachuSpriteStateData + ld a, $ff + ld [wSpritePikachuStateData1ImageIndex], a + call ClearPikachuFollowCommandBuffer + call CalculatePikachuFacingDirection + ret + +.normal_spawn_state + call CalculatePikachuPlacementCoords + xor a + ld [wPikachuSpawnState], a + ld a, [wSpritePlayerStateData1FacingDirection] + ld [wSpritePikachuStateData1FacingDirection], a + ret + +ClearPikachuSpriteStateData:: + ld hl, wSpritePikachuStateData1PictureID + call .clear + ld hl, wSpritePikachuStateData2 +.clear + ld bc, $10 + xor a + call FillMemory + ret + +CalculatePikachuSpawnCoordsAndFacing:: + call CalculatePikachuPlacementCoords + call CalculatePikachuFacingDirection + xor a + ld [wPikachuSpawnState], a + ret + +CalculatePikachuPlacementCoords:: + ld bc, wSpritePikachuStateData1PictureID + ld a, [wYCoord] + add $4 + ld e, a + ld a, [wXCoord] + add $4 + ld d, a + ld a, [wPikachuSpawnState] + and a + jr z, .load_coords + cp $1 + jr z, .right_of_player + cp $2 + jr z, .check_player_facing2 + cp $3 + jr z, .load_coords + cp $4 + jr z, .below_player + cp $5 + jr z, .above_player + cp $6 + jr z, .left_of_player + cp $7 + jr z, .check_player_facing + jr .right_of_player + +.check_player_facing + ld a, [wSpritePlayerStateData1FacingDirection] + and a ; SPRITE_FACING_DOWN + jr z, .below_player + cp SPRITE_FACING_UP + jr z, .above_player + cp SPRITE_FACING_LEFT + jr z, .left_of_player + cp SPRITE_FACING_RIGHT + jr z, .right_of_player +.check_player_facing2 + ld a, [wSpritePlayerStateData1FacingDirection] + and a + jr nz, .check_up + dec e + jr .load_coords + +.check_up + cp SPRITE_FACING_UP + jr nz, .check_left + inc e + jr .load_coords + +.check_left + cp SPRITE_FACING_LEFT + jr nz, .left_of_player_2 + inc d + jr .load_coords + +.left_of_player_2 + dec d + jr .load_coords + +.right_of_player + inc d + jr .load_coords + +.left_of_player + dec d + jr .load_coords + +.below_player + inc e + jr .load_coords + +.above_player + dec e + jr .load_coords ; useless jr +.load_coords + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld [hl], e + inc hl + ld [hl], d + inc hl + ld [hl], $fe + push hl + ld hl, wd472 + set 5, [hl] + pop hl + ret + +CalculatePikachuFacingDirection:: + ld a, $49 + ld [wSpritePikachuStateData1PictureID], a + ld a, $ff + ld [wSpritePikachuStateData1ImageIndex], a + ld a, [wPikachuSpawnState] + and a + jr z, .copy_player_facing + cp $1 + jr z, .copy_player_facing + cp $3 + jr z, .force_facing_down + cp $4 + jr z, .copy_player_facing + cp $6 + jr z, .copy_player_facing + cp $7 + jr z, .face_the_other_way + call ComputePikachuFacingDirection + ret + +.copy_player_facing + ld a, [wSpritePlayerStateData1FacingDirection] + ld [wSpritePikachuStateData1FacingDirection], a + ret + +.force_facing_down + ld a, SPRITE_FACING_DOWN + ld [wSpritePikachuStateData1FacingDirection], a + ret + +.face_the_other_way + ld a, [wSpritePlayerStateData1FacingDirection] + xor $4 + ld [wSpritePikachuStateData1FacingDirection], a + ret + +SetPikachuSpawnOutside:: + ld a, [wCurMap] + cp OAKS_LAB + jr z, .oaks_lab + cp ROUTE_22_GATE + jr z, .route_22_gate + cp MT_MOON_B1F + jr z, .mt_moon_2 + cp ROCK_TUNNEL_1F + jr z, .rock_tunnel_1 + ld a, [wCurMap] + ld hl, Pointer_fc64b + call Pikachu_IsInArray ; similar to IsInArray, but not the same + jr c, .map_list_1 + ld a, [wCurMap] + ld hl, Pointer_fc653 + call Pikachu_IsInArray + jr nc, .not_map_list_2 + ld a, [wSpritePlayerStateData1FacingDirection] + and a + jr nz, .not_map_list_2 + ld a, $3 + jr .load + +.route_22_gate + ld a, [wSpritePlayerStateData1FacingDirection] + and a + jr z, .rock_tunnel_1 + jr .not_map_list_2 + +.mt_moon_2 + ld a, $3 + jr .load + +.map_list_1 + ld a, $4 + jr .load + +.oaks_lab + ld a, $6 + jr .load + +.not_map_list_2 + ld a, $1 + jr .load + +.rock_tunnel_1 + ld a, $3 +.load + ld [wPikachuSpawnState], a + ret + +Pointer_fc64b:: + db VICTORY_ROAD_2F + db ROUTE_7_GATE + db ROUTE_8_GATE + db ROUTE_16_GATE_1F + db ROUTE_18_GATE_1F + db ROUTE_15_GATE_1F + db ROUTE_11_GATE_1F + db $ff + +Pointer_fc653:: + db VIRIDIAN_FOREST_NORTH_GATE + db CERULEAN_BADGE_HOUSE + db CERULEAN_TRASHED_HOUSE + db VERMILION_DOCK + db CELADON_MANSION_1F + db ROUTE_2_GATE + db FUCHSIA_GOOD_ROD_HOUSE + db $ff + +SetPikachuSpawnWarpPad:: + ld a, [wCurMap] + cp VIRIDIAN_FOREST_NORTH_GATE + jr z, .viridian_forest_exit + cp VIRIDIAN_FOREST_SOUTH_GATE + jr z, .viridian_forest_entrance + ld a, [wCurMap] + ld hl, Pointer_fc68e + call Pikachu_IsInArray + jr c, .in_array + jr .not_in_array + +.viridian_forest_exit + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + jr z, .in_array + jr .not_in_array + +.viridian_forest_entrance + ld a, [wSpritePlayerStateData1FacingDirection] + and a ; SPRITE_FACING_DOWN + jr z, .not_in_array + jr .in_array + +.not_in_array + ld a, $0 + jr .load_spawn_state + +.in_array + ld a, $1 +.load_spawn_state + ld [wPikachuSpawnState], a + ret + +Pointer_fc68e:: + db VIRIDIAN_FOREST + db SAFARI_ZONE_CENTER_REST_HOUSE + db SAFARI_ZONE_WEST_REST_HOUSE + db SAFARI_ZONE_EAST_REST_HOUSE + db SAFARI_ZONE_NORTH_REST_HOUSE + db SAFARI_ZONE_SECRET_HOUSE + db SILPH_CO_ELEVATOR + db CELADON_MART_ELEVATOR + db CINNABAR_LAB_TRADE_ROOM + db CINNABAR_LAB_METRONOME_ROOM + db CINNABAR_LAB_FOSSIL_ROOM + db $ff + +SetPikachuSpawnBackOutside:: + ld a, [wCurMap] + cp ROUTE_22_GATE + jr z, .asm_fc6a7 + cp ROUTE_2_GATE + jr z, .asm_fc6b0 + jr .asm_fc6bd + +.asm_fc6a7 + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + jr z, .asm_fc6b9 + jr .asm_fc6bd + +.asm_fc6b0 + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + jr z, .asm_fc6b9 + jr .asm_fc6bd + +.asm_fc6b9 + ld a, $1 + jr .asm_fc6c1 + +.asm_fc6bd + ld a, $3 + jr .asm_fc6c1 + +.asm_fc6c1 + ld [wPikachuSpawnState], a + ret + +SetPikachuOverworldStateFlag2:: + push hl + ld hl, wPikachuOverworldStateFlags + set 2, [hl] + pop hl + ret + +ResetPikachuOverworldStateFlag2:: + push hl + ld hl, wPikachuOverworldStateFlags + res 2, [hl] + pop hl + ret + +SpawnPikachu_:: + call ResetPikachuOverworldStateFlag2 + call TrySpawnPikachu + ret nc + + push bc + call WillPikachuSpawnOnTheScreen + pop bc + ret c + + ld bc, wSpritePikachuStateData1 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + bit 7, [hl] + jp nz, Func_fc745 + ld a, [wFontLoaded] + bit 0, a + jp nz, Func_fc76a + call CheckPikachuFollowingPlayer + jp nz, Func_fc76a + ld a, [hl] + and $7f + cp $a + jr c, .valid + xor a +.valid + add a + ld e, a + ld d, 0 + ld hl, PointerTable_fc710 + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +PointerTable_fc710: + dw Func_fc793 + dw Func_fc7aa + dw Func_fc803 + dw asm_fc9c3 + dw asm_fca1c + dw asm_fc9ee + dw asm_fc87f + dw asm_fc904 + dw asm_fc937 + dw asm_fc969 + dw .nop + +.nop: + ret + +TrySpawnPikachu: + call ShouldPikachuSpawn + jr nc, .dont_spawn + ld a, [wSpritePikachuStateData1MovementStatus] + and a + jr nz, .already_spawned + push bc + push hl + call CalculatePikachuSpawnCoordsAndFacing + pop hl + pop bc +.already_spawned + scf + ret + +.dont_spawn + ld hl, wSpritePikachuStateData1ImageIndex + ld [hl], $ff + dec hl + ld [hl], $0 + xor a + ret + +Func_fc745: + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + res 7, [hl] + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + call CheckPikachuFollowingPlayer + jr nz, .okay + ; Have Pikachu face in the opposite direction of you + ld a, [wSpritePlayerStateData1FacingDirection] + xor $4 + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a +.okay + xor a + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld [hli], a + ld [hl], a + call UpdatePikachuWalkingSprite + ret + +Func_fc76a: + xor a + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld [hli], a + ld [hl], a + call UpdatePikachuWalkingSprite + call Func_fc82e + jr c, .skip + push bc + callfar InitializeSpriteScreenPosition + pop bc +.skip + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $0 + call RefreshPikachuFollow + ret + +Func_fc793: + call RefreshPikachuFollow + push bc + callfar InitializeSpriteScreenPosition + pop bc + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], $ff + dec hl + ld [hl], $1 + ret + +Func_fc7aa: + call Func_fcc92 + jp c, Func_fc803 + dec a + ld l, a + ld h, $0 + add hl, hl + add hl, hl + ld de, Pointer_fc7e3 + add hl, de + ld d, h + ld e, l + ld a, [de] + inc de + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + ld a, [de] + inc de + ld hl, wSpritePikachuStateData1XStepVector - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + dec hl + dec hl + ld a, [de] + ld [hl], a + inc de + ld a, [de] + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + cp $4 + jp z, Func_fca0a + call AreThereAtLeastTwoStepsInPikachuFollowCommandBuffer + jp c, FastPikachuFollow + jp NormalPikachuFollow + +Pointer_fc7e3: + db 0, 0 + db 1, 3 + db 4, 0 + db -1, 3 + db 8, -1 + db 0, 3 + db 12, 1 + db 0, 3 + db 0, 0 + db 1, 4 + db 4, 0 + db -1, 4 + db 8, -1 + db 0, 4 + db 12, 1 + db 0, 4 + +Func_fc803: + call Func_fcae2 + ret c + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + jr nz, .asm_fc823 + push hl + call GetPikachuFollowCommand + pop hl + cp $5 + jr nc, Func_fc842 + ld [hl], $20 + call Random + and $c + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a +.asm_fc823 + xor a + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld [hli], a + ld [hl], a + call UpdatePikachuWalkingSprite + ret + +Func_fc82e: + ld a, [wWalkCounter] + and a + ret z + scf + ret + +Func_fc835: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $10 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +Func_fc842: + ld hl, $0 + push af + call Random + ldh a, [hRandomAdd] + and %11 + ld e, a + ld d, $0 + ld hl, PointerTable_fc85a + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + pop af + jp hl + +PointerTable_fc85a: + dw Func_fc862 + dw Func_fc8f8 + dw Func_fc92b + dw Func_fc95d + +Func_fc862: + dec a + add a + add a + and $c + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $6 + xor a + ld [wd432], a + ld [wd433], a + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $11 +asm_fc87f: + ld a, [wd432] + ld e, a + ld a, [wd433] + ld d, a + call Func_fc82e + jr c, Func_fc8c7 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + sub e + ld e, a + inc hl + inc hl + ld a, [hl] + sub d + ld d, a + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + dec a + add a + add LOW(Pointer_fc8d6) + ld l, a + ld a, HIGH(Pointer_fc8d6) + adc 0 + ld h, a + ld a, [hli] + ld [wd432], a + add e + ld e, a + ld a, [hl] + ld [wd433], a + add d + ld d, a + ld hl, wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + add hl, bc + ld [hl], e + inc hl + inc hl + ld [hl], d + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +Func_fc8c7: + ld hl, wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + sub e + ld [hl], a + inc hl + inc hl + ld a, [hl] + sub d + ld [hl], a + jp Func_fc835 + +Pointer_fc8d6: + db 0, 0 + db -2, 1 + db -4, 2 + db -2, 3 + db 0, 4 + db -2, 3 + db -4, 2 + db -2, 1 + db 0, 0 + db -2, -1 + db -4, -2 + db -2, -3 + db 0, -4 + db -2, -3 + db -4, -2 + db -2, -1 + db 0, 0 + +Func_fc8f8: + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $7 + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $30 +asm_fc904: + call Func_fc82e + jp c, Func_fc835 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp $8 + ld [hl], a + jr nz, .asm_fc91f + xor a + ld [hli], a + ld a, [hl] + inc a + and %11 + ld [hl], a +.asm_fc91f + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +Func_fc92b: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $20 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $8 +asm_fc937: + call Func_fc82e + jp c, Func_fc835 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp $8 + ld [hl], a + jr nz, .asm_fc951 + xor a + ld [hli], a + ld a, [hl] + xor $1 + ld [hl], a +.asm_fc951 + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +Func_fc95d: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $20 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $9 +asm_fc969: + call Func_fc82e + jp c, Func_fc835 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp $8 + ld [hl], a + jr nz, .skip + xor a + ld [hl], a + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + call .TurnClockwise + ld [hl], a +.skip + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +.TurnClockwise: + push hl + ld hl, .Facings + ld d, a +.loop + ld a, [hli] + cp d + jr nz, .loop + ld a, [hl] + pop hl + ret + +.TurnCounterclockwise: + push hl + ld hl, .Facings_End + ld d, a +.loop_ + ld a, [hld] + cp d + jr nz, .loop_ + ld a, [hl] + pop hl + ret + +.Facings: + db SPRITE_FACING_DOWN, SPRITE_FACING_LEFT, SPRITE_FACING_UP, SPRITE_FACING_RIGHT + db SPRITE_FACING_DOWN, SPRITE_FACING_LEFT, SPRITE_FACING_UP, SPRITE_FACING_RIGHT +.Facings_End: + +NormalPikachuFollow: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $8 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $3 + call AddPikachuStepVector +asm_fc9c3: + call TryDoubleAddPikachuStepVectorToScreenPixelCoords + call GetPikachuWalkingAnimationSpeed + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + call ResetPikachuStepVector + call ComputePikachuFacingDirection + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +FastPikachuFollow: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $4 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $5 + call AddPikachuStepVector +asm_fc9ee: + call DoubleAddPikachuStepVectorToScreenPixelCoords + call GetPikachuWalkingAnimationSpeed + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + call ResetPikachuStepVector + call ComputePikachuFacingDirection + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +Func_fca0a: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $8 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $4 + call AddPikachuStepVector + call AddPikachuStepVector +asm_fca1c: + call DoubleAddPikachuStepVectorToScreenPixelCoords + call GetPikachuWalkingAnimationSpeed + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + call ResetPikachuStepVector + call ComputePikachuFacingDirection + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +AddPikachuStepVector: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + ld e, [hl] + inc hl + inc hl + ld d, [hl] + ld hl, wSpritePikachuStateData2MapY - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + add e + ld [hli], a + ld a, [hl] + add d + ld [hl], a + ret + +TryDoubleAddPikachuStepVectorToScreenPixelCoords: + ld a, [wWalkBikeSurfState] + cp $1 ; biking + jr nz, AddPikachuStepVectorToScreenPixelCoords + ld a, [wd736] + bit 6, a + jr nz, AddPikachuStepVectorToScreenPixelCoords +DoubleAddPikachuStepVectorToScreenPixelCoords: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + ld a, [hli] + add a + add a + add [hl] + ld [hli], a + ld a, [hli] + add a + add a + add [hl] + ld [hl], a + ret + +AddPikachuStepVectorToScreenPixelCoords: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + ld a, [hli] + add a + add [hl] + ld [hli], a + ld a, [hli] + add a + add [hl] + ld [hli], a + ret + +ResetPikachuStepVector: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + xor a + ld [hli], a + inc hl + ld [hl], a + ret + +GetPikachuWalkingAnimationSpeed: + call ComparePikachuHappinessTo80 + ld d, $2 + jr nc, .happy + ld d, $5 +.happy + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp d + jr nz, .dont_reset + xor a +.dont_reset + ld [hli], a + ret nz + ld a, [hl] + inc a + and $3 + ld [hl], a + ret + +UpdatePikachuWalkingSprite: + ld a, [wPikachuOverworldStateFlags] + bit 3, a + jr nz, .uninitialized + ld hl, wSpritePikachuStateData2ImageBaseOffset - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + dec a + swap a + ld d, a + ld a, [wd736] + bit 7, a + jr nz, .copy_player + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + or d + ld d, a + ld a, [wFontLoaded] + bit 0, a + jr z, .normal_get_sprite_index + call Func_fcae2 + ret c + jr .load_sprite_index + +.normal_get_sprite_index + ld hl, wSpritePikachuStateData1AnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, d + or [hl] + ld d, a +.load_sprite_index + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], d + ret + +.uninitialized + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], $ff + ret + +.copy_player + ld a, [wSpritePlayerStateData1ImageIndex] + and $f + or d + ld [wSpritePikachuStateData1ImageIndex], a + ret + +Func_fcae2: + ld hl, wSpritePikachuStateData2MapY - wSpritePikachuStateData1 + add hl, bc + ld a, [wYCoord] + add $4 + cp [hl] + jr nz, .on_screen + inc hl + ld a, [wXCoord] + add $4 + cp [hl] + jr nz, .on_screen + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], $ff + scf + ret + +.on_screen + and a + ret + +IsPikachuRightNextToPlayer: + push bc + push de + push hl + ld bc, wSpritePikachuStateData1PictureID + ld a, [wXCoord] + add $4 + ld d, a + ld a, [wYCoord] + add $4 + ld e, a + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + sub e + and a + jr z, .equal + cp $ff + jr z, .one_away + cp $1 + jr z, .one_away + jr .bad + +.one_away + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + sub d + jr z, .good + jr .bad + +.equal + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + sub d + cp $ff + jr z, .good + cp $1 + jr z, .good + and a + jr z, .good + jr .bad + +.good + pop hl + pop de + pop bc + scf + ret + +.bad + pop hl + pop de + pop bc + xor a + ret + +GetPikachuFacingDirectionAndReturnToE:: + call GetPikachuFacingDirection + ld e, a + ret + +GetPikachuFacingDirection: + ld bc, wSpritePikachuStateData1PictureID + ld a, [wXCoord] + add $4 + ld d, a + ld a, [wYCoord] + add $4 + ld e, a + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + cp e + jr z, .asm_fcb71 + jr nc, .asm_fcb6e + ld a, SPRITE_FACING_UP + ret + +.asm_fcb6e + ld a, SPRITE_FACING_DOWN + ret + +.asm_fcb71 + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + cp d + jr z, .asm_fcb81 + jr nc, .asm_fcb7e + ld a, SPRITE_FACING_LEFT + ret + +.asm_fcb7e + ld a, SPRITE_FACING_RIGHT + ret + +.asm_fcb81 + ld a, $ff ; standing + ret + +ClearPikachuFollowCommandBuffer: + push bc + ld hl, wPikachuFollowCommandBufferSize + ld [hl], $ff + inc hl + ld bc, $10 + xor a + call FillMemory + pop bc + ret + +AppendPikachuFollowCommandToBuffer: + ld hl, wPikachuFollowCommandBufferSize + inc [hl] + ld e, [hl] + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + ld [hl], a + ret + +RefreshPikachuFollow: + call ClearPikachuFollowCommandBuffer + call ComputePikachuFollowCommand + ret c + call AppendPikachuFollowCommandToBuffer + ret + +ComputePikachuFollowCommand: + ld bc, wSpritePikachuStateData1PictureID + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [wYCoord] + add $4 + sub [hl] + jr z, .checkXCoord + jr c, .pikaAbovePlayer + call CheckAbsoluteValueLessThan2 + jr c, .return1 + ld a, $5 + and a + ret + +.return1 + ld a, $1 + and a + ret + +.pikaAbovePlayer + call CheckAbsoluteValueLessThan2 + jr c, .return2 + ld a, $6 + and a + ret + +.return2 + ld a, $2 + and a + ret + +.checkXCoord + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [wXCoord] + add $4 + sub [hl] + jr z, .pikachuOnTopOfPlayer + jr c, .pikaToLeftOfPlayer + call CheckAbsoluteValueLessThan2 + jr c, .return4 + ld a, $8 + and a + ret + +.return4 + ld a, $4 + and a + ret + +.pikaToLeftOfPlayer + call CheckAbsoluteValueLessThan2 + jr c, .return3 + ld a, $7 + and a + ret + +.return3 + ld a, $3 + and a + ret + +.pikachuOnTopOfPlayer + scf + ret + +CheckAbsoluteValueLessThan2: + jr nc, .positive + cpl + inc a +.positive + cp $2 + ret + +Func_fcc08:: + call Func_fcc23 + ret nc + ld a, [wd736] + bit 6, a + jr nz, .asm_fcc1b + call Func_fcc42 + ret c + call AppendPikachuFollowCommandToBuffer + ret + +.asm_fcc1b + call Func_fcc64 + ret c + call AppendPikachuFollowCommandToBuffer + ret + +Func_fcc23: + ld a, [wPikachuOverworldStateFlags] + bit 5, a + jr nz, .asm_fcc40 + ld a, [wPikachuOverworldStateFlags] + bit 7, a + jr nz, .asm_fcc40 + ld a, [wd472] + bit 7, a + jr z, .asm_fcc40 + ld a, [wWalkBikeSurfState] + and a + jr nz, .asm_fcc40 + scf + ret + +.asm_fcc40 + and a + ret + +Func_fcc42: + xor a + ld a, [wPlayerDirection] + bit 3, a + jr nz, .asm_fcc58 + bit 2, a + jr nz, .asm_fcc5b + bit 1, a + jr nz, .asm_fcc5e + bit 0, a + jr nz, .asm_fcc61 + scf + ret + +.asm_fcc58 + ld a, $2 + ret + +.asm_fcc5b + ld a, $1 + ret + +.asm_fcc5e + ld a, $3 + ret + +.asm_fcc61 + ld a, $4 + ret + +Func_fcc64: + ld hl, wPikachuOverworldStateFlags + bit 6, [hl] + jr z, .asm_fcc6e + res 6, [hl] + ret + +.asm_fcc6e + set 6, [hl] + xor a + ld a, [wPlayerDirection] + bit 3, a + jr nz, .asm_fcc86 + bit 2, a + jr nz, .asm_fcc89 + bit 1, a + jr nz, .asm_fcc8c + bit 0, a + jr nz, .asm_fcc8f + scf + ret + +.asm_fcc86 + ld a, $6 + ret + +.asm_fcc89 + ld a, $5 + ret + +.asm_fcc8c + ld a, $7 + ret + +.asm_fcc8f + ld a, $8 + ret + +Func_fcc92: + ld hl, wPikachuFollowCommandBufferSize + ld a, [hl] + cp $ff + jr z, .asm_fccb0 + and a + jr z, .asm_fccb0 + dec [hl] + ld e, a + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + inc e + ld a, $ff +.asm_fcca8 + ld d, [hl] + ldd [hl], a + ld a, d + dec e + jr nz, .asm_fcca8 + and a + ret + +.asm_fccb0 + scf + ret + +ComputePikachuFacingDirection:: + call GetPikachuFollowCommandIfBufferSizeNonzero + and a + jr z, .check_y + dec a + and $3 + add a + add a + jr .load + +.check_y + ld a, [wYCoord] + add $4 + ld d, a + ld a, [wXCoord] + add $4 + ld e, a + ld a, [wSpritePikachuStateData2MapY] + cp d + jr z, .check_x + ld a, SPRITE_FACING_DOWN + jr c, .load + ld a, SPRITE_FACING_UP + jr .load + +.check_x + ld a, [wSpritePikachuStateData2MapX] + cp e + jr z, .copy_from_player + ld a, SPRITE_FACING_RIGHT + jr c, .load + ld a, SPRITE_FACING_LEFT + jr .load + +.copy_from_player + ld a, [wSpritePlayerStateData1FacingDirection] +.load + ld [wSpritePikachuStateData1FacingDirection], a + ret + +GetPikachuFollowCommand: + ld hl, wPikachuFollowCommandBufferSize + ld a, [hl] + cp $ff + jr z, .asm_fccff + ld e, a + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + ld a, [hl] + ret + +.asm_fccff + xor a + ret + +GetPikachuFollowCommandIfBufferSizeNonzero: + ld hl, wPikachuFollowCommandBufferSize + ld a, [hl] + cp $ff + jr z, .default + and a + jr z, .default + ld e, a + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + ld a, [hl] + ret + +.default + xor a + ret + +AreThereAtLeastTwoStepsInPikachuFollowCommandBuffer: + ld a, [wPikachuFollowCommandBufferSize] + cp $ff + ret z + cp $2 + jr nc, .set_carry + and a + ret + +.set_carry + scf + ret + +WillPikachuSpawnOnTheScreen: + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] ; If we're here, this can only be $f0 + add wSpritePikachuStateData2MapY - wSpritePikachuStateData2 + ld l, a + ld b, [hl] + ld a, [wYCoord] + cp b + jr z, .same_y + jr nc, .not_on_screen + add (SCREEN_HEIGHT / 2) - 1 + cp b + jr c, .not_on_screen +.same_y + inc l + ld b, [hl] + ld a, [wXCoord] + cp b + jr z, .same_x + jr nc, .not_on_screen + add (SCREEN_WIDTH / 2) - 1 + cp b + jr c, .not_on_screen +.same_x + call .GetNPCCurrentTile + ld d, $60 + ld a, [hli] + ld e, a + cp d + jr nc, .not_on_screen + ld a, [hld] + cp d + jr nc, .not_on_screen + ld bc, -20 + add hl, bc + ld a, [hli] + cp d + jr nc, .not_on_screen + ld a, [hl] + cp d + jr c, .on_screen +.not_on_screen + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + ld l, a + ld [hl], $ff + scf + jr .return + +.on_screen + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add wSpritePikachuStateData2GrassPriority - wSpritePikachuStateData2 + ld l, a + ld a, [wGrassTile] + cp e + ld a, $0 + jr nz, .priority + ld a, $80 +.priority + ld [hl], a + and a +.return + ret + +.GetNPCCurrentTile: + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + ld l, a + ld a, [hli] + add $4 + and $f0 + srl a + ld c, a + ld b, $0 + inc l + ld a, [hl] + add $2 + srl a + srl a + srl a + add SCREEN_WIDTH + ld d, 0 + ld e, a + ld hl, wTileMap +REPT 5 + add hl, bc +ENDR + add hl, de + ret + +ComparePikachuHappinessTo80: +; preserves a and bc + push bc + push af + ld a, [wPikachuHappiness] + cp 80 + pop bc + ld a, b + pop bc + ret diff --git a/engine/pikachu/pikachu_movement.asm b/engine/pikachu/pikachu_movement.asm new file mode 100755 index 00000000..6b912e61 --- /dev/null +++ b/engine/pikachu/pikachu_movement.asm @@ -0,0 +1,1048 @@ +ApplyPikachuMovementData_:: + ld a, b + ld [wPikachuMovementScriptBank], a + ld a, l + ld [wPikachuMovementScriptAddress], a + ld a, h + ld [wPikachuMovementScriptAddress + 1], a + call .SwapSpriteStateData +.loop + call LoadPikachuMovementCommandData + jr nc, .done + call ExecutePikachuMovementCommand + jr .loop + +.done + call .SwapSpriteStateData + call DelayFrame + ret + +.SwapSpriteStateData: + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + push hl + push de + push bc + + ld hl, wSpritePlayerStateData1 + ld de, wSpritePikachuStateData1 + ld c, $10 + call .SwapBytes + + ld hl, wSpritePlayerStateData2 + ld de, wSpritePikachuStateData2 + ld c, $10 + call .SwapBytes + + pop bc + pop de + pop hl + pop af + ld [wUpdateSpritesEnabled], a + ret + +.SwapBytes: + ld b, [hl] + ld a, [de] + ld [hli], a + ld a, b + ld [de], a + inc de + dec c + jr nz, .SwapBytes + ret + +LoadPikachuMovementCommandData: + call GetPikachuMovementScriptByte + cp $3f + ret z + ld c, a + ld b, 0 + ld hl, PikachuMovementDatabase + add hl, bc + add hl, bc + add hl, bc + add hl, bc + ld a, [hli] + ld [wCurPikaMovementFunc1], a + ld a, [hli] + cp $80 + jr nz, .no_param + call GetPikachuMovementScriptByte +.no_param + ld [wCurPikaMovementParam1], a + ld a, [hli] + ld [wCurPikaMovementFunc2], a + ld a, [hli] + cp $80 + jr nz, .no_param2 + call GetPikachuMovementScriptByte +.no_param2 + ld [wCurPikaMovementParam2], a + xor a + ld [wd451], a + scf + ret + +ExecutePikachuMovementCommand: + xor a + ld [wPikachuMovementFlags], a + ld [wPikachuStepTimer], a + ld [wPikachuStepSubtimer], a + ld a, [wSpritePlayerStateData2GrassPriority] + push af +.loop + ld bc, wSpritePlayerStateData1 ; Currently holds Pikachu's sprite state data + ld a, [wCurPikaMovementFunc1] + ld hl, PikaMovementFunc1Jumptable + call .JumpTable + ld a, [wCurPikaMovementFunc2] + ld hl, PikaMovementFunc2Jumptable + call .JumpTable + call GetCoordsForPikachuShadow + call AnimatePikachuShadow + call DelayFrame + call DelayFrame + ld hl, wPikachuMovementFlags + bit 7, [hl] + jr z, .loop + pop af + ld [wSpritePlayerStateData2GrassPriority], a + scf + ret + +.JumpTable: + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +GetCoordsForPikachuShadow: + ld hl, wSpritePlayerStateData1ImageIndex - wSpritePlayerStateData1 + add hl, bc + ld a, [wCurPikaMovementSpriteImageIdx] + ld [hl], a + ld a, [wPikaSpriteY] + ld d, a + ld a, [wPikachuMovementYOffset] + add d + ld hl, wSpritePlayerStateData1YPixels - wSpritePlayerStateData1 + add hl, bc + ld [hl], a + ld a, [wPikaSpriteX] + ld d, a + ld a, [wPikachuMovementXOffset] + add d + ld hl, wSpritePlayerStateData1XPixels - wSpritePlayerStateData1 + add hl, bc + ld [hl], a + ld hl, wPikachuMovementFlags + bit 6, [hl] + ret z + ld hl, wSpritePlayerStateData2GrassPriority - wSpritePlayerStateData1 + add hl, bc + ld [hl], 0 + ret + +AnimatePikachuShadow: + ld hl, wPikachuMovementFlags + bit 6, [hl] + res 6, [hl] + ld hl, wd736 + res 6, [hl] + ret z + set 6, [hl] + call LoadPikachuShadowOAMData + ret + +PikachuMovementDatabase: + db $01, 1 - 1, $00, 1 - 1 ; $00 start + + db $03, $80, $01, 1 - 1 ; $01 + db $04, $80, $01, 1 - 1 ; $02 + db $05, $80, $01, 1 - 1 ; $03 + db $06, $80, $01, 1 - 1 ; $04 + db $07, $80, $01, 1 - 1 ; $05 + db $08, $80, $01, 1 - 1 ; $06 + db $09, $80, $01, 1 - 1 ; $07 + db $0a, $80, $01, 1 - 1 ; $08 + + db $03, $80, $06, 1 - 1 ; $09 + db $04, $80, $06, 1 - 1 ; $0a + db $05, $80, $06, 1 - 1 ; $0b + db $06, $80, $06, 1 - 1 ; $0c + db $07, $80, $06, 1 - 1 ; $0d + db $08, $80, $06, 1 - 1 ; $0e + db $09, $80, $06, 1 - 1 ; $0f + db $0a, $80, $06, 1 - 1 ; $10 + + db $03, $80, $03, $80 ; $11 + db $04, $80, $03, $80 ; $12 + db $05, $80, $03, $80 ; $13 + db $06, $80, $03, $80 ; $14 + db $07, $80, $03, $80 ; $15 + db $08, $80, $03, $80 ; $16 + db $09, $80, $03, $80 ; $17 + db $0a, $80, $03, $80 ; $18 + + db $03, $80, $07, $80 ; $19 + db $04, $80, $07, $80 ; $1a + db $05, $80, $07, $80 ; $1b + db $06, $80, $07, $80 ; $1c + + db $0b, (1 << 5) | 8 - 1, $02, 1 - 1 ; $1d step down + db $0c, (1 << 5) | 8 - 1, $02, 1 - 1 ; $1e step up + db $0d, (1 << 5) | 8 - 1, $02, 1 - 1 ; $1f step left + db $0e, (1 << 5) | 8 - 1, $02, 1 - 1 ; $20 step right + db $0f, (1 << 5) | 8 - 1, $02, 1 - 1 ; $21 step down left + db $10, (1 << 5) | 8 - 1, $02, 1 - 1 ; $22 step down right + db $11, (1 << 5) | 8 - 1, $02, 1 - 1 ; $23 step up left + db $12, (1 << 5) | 8 - 1, $02, 1 - 1 ; $24 step up right + + db $0b, 16 - 1, $02, 1 - 1 ; $25 slide down + db $0c, 16 - 1, $02, 1 - 1 ; $26 slide up + db $0d, 16 - 1, $02, 1 - 1 ; $27 slide left + db $0e, 16 - 1, $02, 1 - 1 ; $28 slide right + db $0f, 16 - 1, $02, 1 - 1 ; $29 slide down left + db $10, 16 - 1, $02, 1 - 1 ; $2a slide down right + db $11, 16 - 1, $02, 1 - 1 ; $2b slide up left + db $12, 16 - 1, $02, 1 - 1 ; $2c slide up right + + db $0b, 16 - 1, $08, (1 << 4) | 8 - 1 ; $2d hop down + db $0c, 16 - 1, $08, (1 << 4) | 8 - 1 ; $2e hop up + db $0d, 16 - 1, $08, (1 << 4) | 8 - 1 ; $2f hop left + db $0e, 16 - 1, $08, (1 << 4) | 8 - 1 ; $30 hop right + db $0f, 16 - 1, $08, (1 << 4) | 8 - 1 ; $31 hop down left + db $10, 16 - 1, $08, (1 << 4) | 8 - 1 ; $32 hop down right + db $11, 16 - 1, $08, (1 << 4) | 8 - 1 ; $33 hop up left + db $12, 16 - 1, $08, (1 << 4) | 8 - 1 ; $34 hop up right + + db $13, 16 - 1, $06, 1 - 1 ; $35 look down + db $14, 16 - 1, $06, 1 - 1 ; $36 look up + db $15, 16 - 1, $06, 1 - 1 ; $37 look left + db $16, 16 - 1, $06, 1 - 1 ; $38 look right + + db $02, $80, $04, 1 - 1 ; $39 + db $02, $80, $05, 1 - 1 ; $3a + db $02, $80, $03, $80 ; $3b + db $02, $80, $07, $80 ; $3c + db $02, $80, $09, $80 ; $3d + db $02, $80, $06, 1 - 1 ; $3e + +PikaMovementFunc1Jumptable: + dw PikaMovementFunc1_EndCommand_ ; 00 + dw PikaMovementFunc1_LoadPikachuCurrentPosition ; 01 + dw PikaMovementFunc1_DelayFrames ; 02 + dw PikaMovementFunc1_WalkInCurrentFacingDirection ; 03 + dw PikaMovementFunc1_WalkInOppositeFacingDirection ; 04 + dw PikaMovementFunc1_StepTurningCounterclockwise ; 05 + dw PikaMovementFunc1_StepTurningClockwise ; 06 + dw PikaMovementFunc1_StepForwardLeft ; 07 + dw PikaMovementFunc1_StepForwardRight ; 08 + dw PikaMovementFunc1_StepBackwardLeft ; 09 + dw PikaMovementFunc1_StepBackwardRight ; 0a + dw PikaMovementFunc1_MoveDown ; 0b + dw PikaMovementFunc1_MoveUp ; 0c + dw PikaMovementFunc1_MoveLeft ; 0d + dw PikaMovementFunc1_MoveRight ; 0e + dw PikaMovementFunc1_MoveDownLeft ; 0f + dw PikaMovementFunc1_MoveDownRight ; 10 + dw PikaMovementFunc1_MoveUpLeft ; 11 + dw PikaMovementFunc1_MoveUpRight ; 12 + dw PikaMovementFunc1_LookDown ; 13 + dw PikaMovementFunc1_LookUp ; 14 + dw PikaMovementFunc1_LookLeft ; 15 + dw PikaMovementFunc1_LookRight ; 16 + dw PikaMovementFunc1_EndCommand_ ; 17 + +PikaMovementFunc1_EndCommand: + ld a, [wPikachuMovementFlags] + set 7, a + ld [wPikachuMovementFlags], a + ret + +PikaMovementFunc1_EndCommand_: + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_LoadPikachuCurrentPosition: + ld hl, wSpritePlayerStateData1YPixels - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + ld [wPikaSpriteY], a + ld hl, wSpritePlayerStateData1XPixels - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + ld [wPikaSpriteX], a + xor a + ld [wPikachuMovementYOffset], a + ld [wPikachuMovementXOffset], a + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_DelayFrames: + call CheckPikachuStepTimer1 + ret nz + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_WalkInCurrentFacingDirection: + call GetPikachuFacing + jr PikaMovementFunc1_ApplyStepVector + +PikaMovementFunc1_WalkInOppositeFacingDirection: + call GetPikachuFacing + xor %100 + jr PikaMovementFunc1_ApplyStepVector + +PikaMovementFunc1_StepTurningCounterclockwise: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_RIGHT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_LEFT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_DOWN << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_UP << 2 + db $ff + +PikaMovementFunc1_StepTurningClockwise: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_LEFT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_RIGHT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_UP << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_DOWN << 2 + db $ff + +PikaMovementFunc1_StepForwardLeft: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_DOWN_RIGHT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_UP_LEFT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_DOWN_LEFT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_UP_RIGHT << 2 + +PikaMovementFunc1_StepForwardRight: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_DOWN_LEFT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_UP_RIGHT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_UP_LEFT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_DOWN_RIGHT << 2 + +PikaMovementFunc1_StepBackwardLeft: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_UP_RIGHT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_DOWN_LEFT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_DOWN_RIGHT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_UP_LEFT << 2 + +PikaMovementFunc1_StepBackwardRight: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_UP_LEFT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_DOWN_RIGHT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_UP_RIGHT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_DOWN_LEFT << 2 + +PikaMovementFunc1_ApplyStepVector: + rrca + rrca + and $7 + ld e, a + call GetPikachuStepVectorMagnitude + ld d, a + call UpdatePikachuPosition + call CheckPikachuStepTimer1 + ret nz + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_GetNextFacing: + push de + ld d, a +.loop + ld a, [hli] + cp d + jr z, .found + inc hl + cp $ff + jr nz, .loop + pop de + ret + +.found + ld a, [hl] + pop de + scf + ret + +PikaMovementFunc1_MoveDown: + ld a, PIKASTEPDIR_DOWN + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveUp: + ld a, PIKASTEPDIR_UP + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveLeft: + ld a, PIKASTEPDIR_LEFT + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveRight: + ld a, PIKASTEPDIR_RIGHT + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveDownLeft: + ld e, PIKASTEPDIR_DOWN_LEFT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_MoveDownRight: + ld e, PIKASTEPDIR_DOWN_RIGHT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_MoveUpLeft: + ld e, PIKASTEPDIR_UP_LEFT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_MoveUpRight: + ld e, PIKASTEPDIR_UP_RIGHT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_ApplyFacingAndMove: + ld e, a + call SetPikachuFacing +PikaMovementFunc1_MoveDiagonally: + call GetPikachuStepVectorMagnitude + ld d, a + push de + call UpdatePikachuPosition + pop de + call CheckPikachuStepTimer1 + ret nz + ld a, e + call ApplyPikachuStepVector + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_LookDown: + ld a, PIKASTEPDIR_DOWN + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_LookUp: + ld a, PIKASTEPDIR_UP + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_LookLeft: + ld a, PIKASTEPDIR_LEFT + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_LookRight: + ld a, PIKASTEPDIR_RIGHT + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_ApplyFacing: + call SetPikachuFacing + call PikaMovementFunc1_EndCommand + ret + +UpdatePikachuPosition: + push de + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + pop de + ld a, d + jp hl + +.Jumptable: + dw .Down + dw .Up + dw .Left + dw .Right + dw .DownLeft + dw .DownRight + dw .UpLeft + dw .UpRight + +.Down: + ld d, 0 + ld e, a + jr .ApplyVector + +.Up: + ld d, 0 + cpl + inc a + ld e, a + jr .ApplyVector + +.Left: + cpl + inc a + ld d, a + ld e, 0 + jr .ApplyVector + +.Right: + ld d, a + ld e, 0 + jr .ApplyVector + +.DownLeft: + ld e, a + cpl + inc a + ld d, a + jr .ApplyVector + +.DownRight: + ld e, a + ld d, a + jr .ApplyVector + +.UpLeft: + cpl + inc a + ld e, a + ld d, a + jr .ApplyVector + +.UpRight: + ld d, a + cpl + inc a + ld e, a + jr .ApplyVector + +.ApplyVector: + ld a, [wPikaSpriteX] + add d + ld [wPikaSpriteX], a + ld a, [wPikaSpriteY] + add e + ld [wPikaSpriteY], a + ret + +PikaMovementFunc2Jumptable: + dw PikaMovementFunc2_ResetFrameCounterAndFaceCurrent ; 0 + dw PikaMovementFunc2_UpdateSpriteImageIdxWithPreviousImageIdxDirection ; 1 + dw PikaMovementFunc2_UpdateSpriteImageIdxWithFacing ; 2 + dw PikaMovementFunc2_TurnParameter ; 3 + dw PikaMovementFunc2_TurnClockwise ; 4 + dw PikaMovementFunc2_TurnCounterClockwise ; 5 + dw PikaMovementFunc2_CopySpriteImageIdxDirectionToSpriteImageIdx ; 6 + dw PikaMovementFunc2_UpdateJumpWithPreviousImageIdxDirection ; 7 + dw PikaMovementFunc2_UpdateJumpWithFacing ; 8 + dw PikaMovementFunc2_CopyFacingToJump ; 9 + dw PikaMovementFunc2_nop ; 10 + +PikaMovement_SetSpawnShadow: + ld hl, wPikachuMovementFlags + set 6, [hl] + ret + +PikaMovementFunc2_ResetFrameCounterAndFaceCurrent: + ld hl, wSpritePlayerStateData1IntraAnimFrameCounter - wSpritePlayerStateData1 + add hl, bc + xor a + ld [hli], a + ld [hl], a + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call GetPikachuFacing + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_nop: + ret + +PikaMovementFunc2_CopySpriteImageIdxDirectionToSpriteImageIdx: + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call PikaMovementFunc2_GetSpriteImageIdxDirection + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_UpdateSpriteImageIdxWithFacing: + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call GetPikachuFacing + or d + ld d, a + jr PikaMovementFunc2_UpdateSpriteImageIdx + +PikaMovementFunc2_UpdateSpriteImageIdxWithPreviousImageIdxDirection: + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call PikaMovementFunc2_GetSpriteImageIdxDirection + or d + ld d, a +PikaMovementFunc2_UpdateSpriteImageIdx: + ld hl, wSpritePlayerStateData1AnimFrameCounter - wSpritePlayerStateData1 + add hl, bc + call CheckPikachuStepTimer2 ; does not preserve hl + jr nz, .skip + inc [hl] +.skip + ld a, [hl] + rrca + rrca + and 3 + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_UpdateJumpWithFacing: + call GetPikachuFacing + ld d, a + jr PikaMovementFunc2_UpdateJump + +PikaMovementFunc2_UpdateJumpWithPreviousImageIdxDirection: + call PikaMovementFunc2_GetSpriteImageIdxDirection + ld d, a +PikaMovementFunc2_UpdateJump: + call PikaMovementFunc2_GetImageBaseOffset + or d + ld d, a + call PikaMovementFunc2_Timer + or d + ld [wCurPikaMovementSpriteImageIdx], a + call PikaMovementFunc_Sine + ld [wPikachuMovementYOffset], a + and a + ret z + call PikaMovement_SetSpawnShadow + ret + +PikaMovementFunc2_CopyFacingToJump: + call GetPikachuFacing + ld d, a + call PikaMovementFunc2_GetImageBaseOffset + or d + ld [wCurPikaMovementSpriteImageIdx], a + call PikaMovementFunc_Sine + ld [wPikachuMovementYOffset], a + ret + +PikaMovementFunc2_TurnParameter: + ld a, [wCurPikaMovementParam2] + and $40 + cp $40 + jr z, PikaMovementFunc2_TurnClockwise + jr PikaMovementFunc2_TurnCounterClockwise + +PikaMovementFunc2_TurnClockwise: + call PikaMovementFunc2_GetSpriteImageIdxDirection + ld d, a + call CheckPikachuStepTimer2 + jr nz, .skip + ld hl, Data_fd731 +.loop + ld a, [hli] + cp d + jr nz, .loop + ld d, [hl] +.skip + call PikaMovementFunc2_GetImageBaseOffset + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_TurnCounterClockwise: + call PikaMovementFunc2_GetSpriteImageIdxDirection + ld d, a + call CheckPikachuStepTimer2 + jr nz, .skip + ld hl, Data_fd731End +.loop + ld a, [hld] + cp d + jr nz, .loop + ld d, [hl] +.skip + call PikaMovementFunc2_GetImageBaseOffset + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +Data_fd731: + db SPRITE_FACING_DOWN + db SPRITE_FACING_LEFT + db SPRITE_FACING_UP + db SPRITE_FACING_RIGHT + db SPRITE_FACING_DOWN +Data_fd731End: + +PikaMovementFunc2_Timer: + push hl + ld hl, wSpritePlayerStateData1IntraAnimFrameCounter - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + inc a + and $3 + ld [hli], a + jr nz, .load_pop + ld a, [hl] + inc a + and $3 + ld [hl], a +.load_pop + ld a, [hl] + pop hl + ret + +PikaMovementFunc2_GetImageBaseOffset: + push hl + ld hl, wSpritePlayerStateData2ImageBaseOffset - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + dec a + swap a + pop hl + ret + +PikaMovementFunc2_GetSpriteImageIdxDirection: + push hl + ld hl, wSpritePlayerStateData1ImageIndex - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + and $c + pop hl + ret + +GetPikachuFacing: + push hl + ld hl, wSpritePlayerStateData1FacingDirection - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + and $c + pop hl + ret + +SetPikachuFacing: + push hl + ld hl, wSpritePlayerStateData1FacingDirection - wSpritePlayerStateData1 + add hl, bc + add a + add a + and $c + ld [hl], a + pop hl + ret + +CheckPikachuStepTimer1: + ld hl, wPikachuStepTimer + inc [hl] + ld a, [wCurPikaMovementParam1] + and $1f + inc a + cp [hl] + ret nz + ld [hl], 0 + ret + +GetPikachuStepVectorMagnitude: + ; *XX***** + ld a, [wCurPikaMovementParam1] + swap a + rrca + and $3 + inc a + ret + +CheckPikachuStepTimer2: + ld hl, wPikachuStepSubtimer + inc [hl] + ld a, [wCurPikaMovementParam2] + and $f + inc a + cp [hl] + ret nz + ld [hl], 0 + ret + +PikaMovementFunc_Sine: + call .GetArgument + ld a, [wPikachuStepSubtimer] + add e + ld [wPikachuStepSubtimer], a + add $20 + ld e, a + push hl + push bc + call Sine_e + pop bc + pop hl + ret + +.GetArgument: + ld a, [wCurPikaMovementParam2] + and $f + inc a + ld d, a + ld a, [wCurPikaMovementParam2] + swap a + and $7 + ld e, a + ld a, 1 + jr z, .okay +.loop + add a + dec e + jr nz, .loop +.okay + ld e, a + ret + +ApplyPikachuStepVector: + push bc + ld c, a + ld b, 0 + ld hl, .StepVectors + add hl, bc + add hl, bc + ld d, [hl] + inc hl + ld e, [hl] + pop bc + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + add e + ld [hli], a + ld a, [hl] + add d + ld [hl], a + ret + +.StepVectors: + db 0, 1 + db 0, -1 + db -1, 0 + db 1, 0 + db -1, 1 + db 1, 1 + db -1, -1 + db 1, -1 + +LoadPikachuShadowOAMData: + push bc + push de + push hl + + ld bc, wOAMBuffer + 4 * 36 + ld a, [wPikaSpriteY] + ld e, a + ld a, [wPikaSpriteX] + ld d, a + ld hl, .OAMData + call .LoadOAMData + + pop hl + pop de + pop bc + ret + +.OAMData: + db 2 + db $0c, $00, $ff, 0 + db $0c, $08, $ff, 1 << OAM_X_FLIP + +.LoadOAMData: + ld a, e + add $10 + ld e, a + ld a, d + add $8 + ld d, a + ld a, [hli] +.loop + push af + ld a, [hli] + add e + ld [bc], a + inc bc + ld a, [hli] + add d + ld [bc], a + inc bc + ld a, [hli] + ld [bc], a + inc bc + ld a, [hli] + ld [bc], a + inc bc + pop af + dec a + jr nz, .loop + ret + +LoadPikachuShadowIntoVRAM:: + ld hl, vNPCSprites2 + $7f * $10 + ld de, LedgeHoppingShadowGFX_3F + lb bc, BANK(LedgeHoppingShadowGFX_3F), (LedgeHoppingShadowGFX_3FEnd - LedgeHoppingShadowGFX_3F) / 8 + jp CopyVideoDataDoubleAlternate + +LedgeHoppingShadowGFX_3F: +INCBIN "gfx/overworld/shadow.1bpp" +LedgeHoppingShadowGFX_3FEnd: + +LoadPikachuBallIconIntoVRAM: + ld hl, vNPCSprites2 + $7e * $10 + ld de, OverworldPikachuBallGFX + lb bc, BANK(OverworldPikachuBallGFX), 1 + jp CopyVideoDataDoubleAlternate + +Func_fd851: + ld hl, vNPCSprites + $c * $10 + ld a, 3 +.loop + push af + push hl + ld de, OverworldPikachuBallGFX + lb bc, BANK(OverworldPikachuBallGFX), 4 + call CopyVideoDataAlternate + pop hl + ld de, 4 * $10 + add hl, de + pop af + dec a + jr nz, .loop + ret + +OverworldPikachuBallGFX: +INCBIN "gfx/overworld/pikachu_ball.2bpp" + +LoadPikachuSpriteIntoVRAM: + ld de, PikachuSprite + lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32 + ld hl, vNPCSprites + $c * $10 + push bc + call CopyVideoDataAlternate + ld de, PikachuSprite + $c * $10 + ld hl, vNPCSprites2 + $c * $10 + ldh a, [hFFFC] + and a + jr z, .load + ld de, PikachuSprite + $c * $10 + ld hl, vNPCSprites2 + $4c * $10 +.load + pop bc + call CopyVideoDataAlternate + call LoadPikachuShadowIntoVRAM + call LoadPikachuBallIconIntoVRAM + ret + +PikachuPewterPokecenterCheck: + ld a, [wCurMap] + cp PEWTER_POKECENTER + ret nz + call EnablePikachuFollowingPlayer + call StarterPikachuEmotionCommand_turnawayfromplayer + ret + +PikachuFanClubCheck: + ld a, [wCurMap] + cp POKEMON_FAN_CLUB + ret nz + call EnablePikachuFollowingPlayer + call StarterPikachuEmotionCommand_turnawayfromplayer + ret + +PikachuBillsHouseCheck: + ld a, [wCurMap] + cp BILLS_HOUSE + ret nz + call EnablePikachuFollowingPlayer + ret + +Pikachu_LoadCurrentMapViewUpdateSpritesAndDelay3: + call LoadCurrentMapView + call UpdateSprites + call Delay3 + ret + +Cosine_e: ; cosine? + ld a, e + add $10 + jr asm_fd908 + +Sine_e: ; sine? + ld a, e +asm_fd908: + and $3f + cp $20 + jr nc, .asm_fd913 + call GetSine + ld a, h + ret + +.asm_fd913 + and $1f + call GetSine + ld a, h + cpl + inc a + ret + +GetSine: + ld e, a + ld a, d + ld d, 0 + ld hl, SineWave_3f + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, 0 +.asm_fd92b + srl a + jr nc, .asm_fd930 + add hl, de +.asm_fd930 + sla e + rl d + and a + jr nz, .asm_fd92b + ret + +SineWave_3f: + sine_wave $100 diff --git a/engine/pikachu/pikachu_pcm.asm b/engine/pikachu/pikachu_pcm.asm new file mode 100755 index 00000000..bf1aa57f --- /dev/null +++ b/engine/pikachu/pikachu_pcm.asm @@ -0,0 +1,154 @@ +PlayPikachuSoundClip:: + ld a, e + ld e, a + ld d, $0 + ld hl, PikachuCriesPointerTable + add hl, de + add hl, de + add hl, de + ld b, [hl] ; bank of pikachu cry data + inc hl + ld a, [hli] ; cry data pointer + ld h, [hl] + ld l, a + ld c, $4 +.loop + dec c + jr z, .done_delay + call DelayFrame + jr .loop + +.done_delay + di + push bc + push hl + ld a, $80 + ldh [rNR52], a + ld a, $77 + ldh [rNR50], a + xor a + ldh [rNR30], a + ld hl, rWave_0 ; wave data + ld de, wRedrawRowOrColumnSrcTiles +.saveWaveDataLoop + ld a, [hl] + ld [de], a + inc de + ld a, $ff + ld [hli], a + ld a, l + cp $40 ; end of wave data + jr nz, .saveWaveDataLoop + ld a, $80 + ldh [rNR30], a + ldh a, [rNR51] + or $44 + ldh [rNR51], a + ld a, $ff + ldh [rNR31], a + ld a, $20 + ldh [rNR32], a + ld a, $ff + ldh [rNR33], a + ld a, $87 + ldh [rNR34], a + pop hl + pop bc + call PlayPikachuPCM + xor a + ld [wc0f3], a + ld [wc0f4], a + ld a, $80 + ldh [rNR52], a + xor a + ldh [rNR30], a + ld hl, rWave_0 + ld de, wRedrawRowOrColumnSrcTiles +.reloadWaveDataLoop + ld a, [de] + inc de + ld [hli], a + ld a, l + cp $40 ; end of wave data + jr nz, .reloadWaveDataLoop + ld a, $80 + ldh [rNR30], a + ldh a, [rNR51] + and $bb + ldh [rNR51], a + xor a + ld [wChannelSoundIDs + Ch5], a + ld [wChannelSoundIDs + Ch6], a + ld [wChannelSoundIDs + Ch7], a + ld [wChannelSoundIDs + Ch8], a + ldh a, [hLoadedROMBank] + ei + ret + +PikachuCriesPointerTable:: +; format: +; db bank +; dw pointer to cry + +; bank 21 + pikacry_def PikachuCry1 + pikacry_def PikachuCry2 + pikacry_def PikachuCry3 + pikacry_def PikachuCry4 + +; bank 22 + pikacry_def PikachuCry5 + pikacry_def PikachuCry6 + pikacry_def PikachuCry7 + +; bank 23 + pikacry_def PikachuCry8 + pikacry_def PikachuCry9 + pikacry_def PikachuCry10 + +; bank 24 + pikacry_def PikachuCry11 + pikacry_def PikachuCry12 + pikacry_def PikachuCry13 + +; bank 25 + pikacry_def PikachuCry14 + pikacry_def PikachuCry15 + +; banks 31-34, in no particular order + + pikacry_def PikachuCry16 + pikacry_def PikachuCry17 + pikacry_def PikachuCry18 + pikacry_def PikachuCry19 + pikacry_def PikachuCry20 + pikacry_def PikachuCry21 + pikacry_def PikachuCry22 + pikacry_def PikachuCry23 + pikacry_def PikachuCry24 + pikacry_def PikachuCry25 + pikacry_def PikachuCry26 + +; bank 35 + pikacry_def PikachuCry27 + pikacry_def PikachuCry28 + pikacry_def PikachuCry29 + pikacry_def PikachuCry30 + pikacry_def PikachuCry31 + +; bank 36 + pikacry_def PikachuCry32 + pikacry_def PikachuCry33 + pikacry_def PikachuCry34 + +; bank 37 + pikacry_def PikachuCry35 + pikacry_def PikachuCry36 + +; banks 36-38 + pikacry_def PikachuCry37 + pikacry_def PikachuCry38 + pikacry_def PikachuCry39 + pikacry_def PikachuCry40 + pikacry_def PikachuCry41 + pikacry_def PikachuCry42 diff --git a/engine/pikachu/pikachu_pic_animation.asm b/engine/pikachu/pikachu_pic_animation.asm new file mode 100755 index 00000000..33a3e504 --- /dev/null +++ b/engine/pikachu/pikachu_pic_animation.asm @@ -0,0 +1,855 @@ +GetPikaPicAnimationScriptIndex: + ld hl, PikachuMoodLookupTable + ld a, [wPikachuMood] + ld d, a +.get_mood_param + ld a, [hli] + inc hl + cp d + jr c, .get_mood_param + dec hl + ld e, [hl] + ld hl, PikaPicAnimationScriptPointerLookupTable + ld a, [wPikachuHappiness] + ld d, a + ld bc, 6 +.get_happiness_param + ld a, [hl] + cp d + jr nc, .got_animation + add hl, bc + jr .get_happiness_param + +.got_animation + ld d, 0 + add hl, de + ld a, [hl] + ret + +PikachuMoodLookupTable: +; First byte: mood threshold +; Second byte: column index in PikaPicAnimationScriptPointerLookupTable + db 40, 1 + db 127, 2 + db 128, 3 + db 210, 4 + db 255, 5 + +PikaPicAnimationScriptPointerLookupTable: +; First byte: happiness threshold +; Remaining bytes: loaded based on Pikachu's mood + db 50 + dpikapic PikaPicAnimScript14 + dpikapic PikaPicAnimScript14 + dpikapic PikaPicAnimScript6 + dpikapic PikaPicAnimScript13 + dpikapic PikaPicAnimScript13 + + db 100 + dpikapic PikaPicAnimScript9 + dpikapic PikaPicAnimScript9 + dpikapic PikaPicAnimScript5 + dpikapic PikaPicAnimScript12 + dpikapic PikaPicAnimScript12 + + db 130 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript1 + dpikapic PikaPicAnimScript8 + dpikapic PikaPicAnimScript8 + + db 160 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript4 + dpikapic PikaPicAnimScript15 + dpikapic PikaPicAnimScript15 + + db 200 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript7 + dpikapic PikaPicAnimScript2 + dpikapic PikaPicAnimScript2 + + db 250 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript16 + dpikapic PikaPicAnimScript10 + dpikapic PikaPicAnimScript10 + + db 255 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript19 + dpikapic PikaPicAnimScript20 + dpikapic PikaPicAnimScript20 + +StarterPikachuEmotionCommand_pikapic: + ldh a, [hAutoBGTransferEnabled] + push af + xor a + ldh [hAutoBGTransferEnabled], a + ld a, [de] + ld [wPikaPicAnimNumber], a + inc de + push de + call .RunPikapic + pop de + pop af + ldh [hAutoBGTransferEnabled], a + ret + +.RunPikapic: + call PlacePikapicTextBoxBorder + callfar LoadOverworldPikachuFrontpicPalettes + call ResetPikaPicAnimBuffer + call LoadCurrentPikaPicAnimScriptPointer + call ExecutePikaPicAnimScript + call PlacePikapicTextBoxBorder + call RunDefaultPaletteCommand + ret + +ResetPikaPicAnimBuffer: + ld hl, wCurPikaMovementData + ld bc, wCurPikaMovementDataEnd - wCurPikaMovementData + xor a + call FillMemory + ld hl, wPikaPicAnimObjectDataBufferSize + ld bc, wPikaPicAnimObjectDataBufferEnd - wPikaPicAnimObjectDataBufferSize + xor a + call FillMemory + call ClearPikaPicUsedGFXBuffer + ld hl, 100 + ld a, l + ld [wPikaPicAnimTimer], a + ld a, h + ld [wPikaPicAnimTimer + 1], a + ld a, $7 + ld [wPikaPicPikaDrawStartX], a + ld a, $6 + ld [wPikaPicPikaDrawStartY], a + ret + +PlacePikapicTextBoxBorder: + xor a + ldh [hAutoBGTransferEnabled], a + hlcoord 6, 5 + lb bc, 5, 5 + call TextBoxBorder + call Delay3 + call UpdateSprites + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + ret + +LoadCurrentPikaPicAnimScriptPointer: + ld a, [wPikaPicAnimNumber] + cp $1d + jr c, .valid + ld a, $0 +.valid + ld e, a + ld d, 0 + ld hl, PikaPicAnimPointers + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call UpdatePikaPicAnimPointer + ret + +pikapic_def: MACRO +\1_id: + dw \1 +ENDM + +PikaPicAnimPointers: + pikapic_def PikaPicAnimScript0 ; 00 + pikapic_def PikaPicAnimScript1 ; 01 + pikapic_def PikaPicAnimScript2 ; 02 + pikapic_def PikaPicAnimScript3 ; 03 + pikapic_def PikaPicAnimScript4 ; 04 + pikapic_def PikaPicAnimScript5 ; 05 + pikapic_def PikaPicAnimScript6 ; 06 + pikapic_def PikaPicAnimScript7 ; 07 + pikapic_def PikaPicAnimScript8 ; 08 + pikapic_def PikaPicAnimScript9 ; 09 + pikapic_def PikaPicAnimScript10 ; 0a + pikapic_def PikaPicAnimScript11 ; 0b + pikapic_def PikaPicAnimScript12 ; 0c + pikapic_def PikaPicAnimScript13 ; 0d + pikapic_def PikaPicAnimScript14 ; 0e + pikapic_def PikaPicAnimScript15 ; 0f + pikapic_def PikaPicAnimScript16 ; 10 + pikapic_def PikaPicAnimScript17 ; 11 + pikapic_def PikaPicAnimScript18 ; 12 + pikapic_def PikaPicAnimScript19 ; 13 + pikapic_def PikaPicAnimScript20 ; 14 + pikapic_def PikaPicAnimScript21 ; 15 + pikapic_def PikaPicAnimScript22 ; 16 + pikapic_def PikaPicAnimScript23 ; 17 + pikapic_def PikaPicAnimScript24 ; 18 + pikapic_def PikaPicAnimScript25 ; 19 + pikapic_def PikaPicAnimScript26 ; 1a + pikapic_def PikaPicAnimScript27 ; 1b + pikapic_def PikaPicAnimScript28 ; 1c + pikapic_def PikaPicAnimScript29 ; 1d + +ExecutePikaPicAnimScript: +.loop + xor a + ldh [hAutoBGTransferEnabled], a + call RunPikaPicAnimSetupScript + call DummyFunction_fdad5 + call AnimateCurrentPikaPicAnimFrame + call DummyFunction_fdad5 + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call PikaPicAnimTimerAndJoypad + and a + jr z, .loop + ret + +PikaPicAnimTimerAndJoypad: + call Delay3 + call CheckPikaPicAnimTimer + and a + ret nz + call JoypadLowSensitivity + ldh a, [hJoyPressed] + and A_BUTTON | B_BUTTON + ret + +CheckPikaPicAnimTimer: + ld hl, wPikaPicAnimTimer + dec [hl] + jr nz, .not_done_yet + inc hl + ld a, [hl] + and a + jr z, .timer_expired + dec [hl] +.not_done_yet + xor a + ret + +.timer_expired + ld a, $1 + ret + +DummyFunction_fdad5: + ret + +AnimateCurrentPikaPicAnimFrame: + ld bc, wPikaPicAnimObjectDataBuffer + ld a, 4 +.loop + push af + push bc + ld hl, 0 ; struct index + add hl, bc + ld a, [hli] + and a + jr z, .skip + ld a, [hli] + ld [wCurPikaPicAnimObjectScriptIdx], a + ld a, [hli] + ld [wCurPikaPicAnimObjectFrameIdx], a + ld a, [hli] + ld [wCurPikaPicAnimObjectFrameTimer], a + ld a, [hli] + ld [wCurPikaPicAnimObjectVTileOffset], a + ld a, [hli] + ld [wCurPikaPicAnimObjectXOffset], a + ld a, [hli] + ld [wCurPikaPicAnimObjectYOffset], a + ld a, [hli] + ld [wCurPikaPicAnimObject + 6], a + push bc + call LoadPikaPicAnimObjectData + pop bc + ld hl, 1 ; script index + add hl, bc + ld a, [wCurPikaPicAnimObjectScriptIdx] + ld [hli], a + ld a, [wCurPikaPicAnimObjectFrameIdx] + ld [hli], a + ld a, [wCurPikaPicAnimObjectFrameTimer] + ld [hli], a + ld a, [wCurPikaPicAnimObjectVTileOffset] + ld [hli], a + ld a, [wCurPikaPicAnimObjectXOffset] + ld [hli], a + ld a, [wCurPikaPicAnimObjectYOffset] + ld [hli], a + ld a, [wCurPikaPicAnimObject + 6] + ld [hl], a +.skip + pop bc + ld hl, 8 + add hl, bc + ld b, h + ld c, l + pop af + dec a + jr nz, .loop + ret + +PikaPicAnimCommand_object: + ld hl, wPikaPicAnimObjectDataBuffer + ld de, 8 + ld c, 4 +.loop + ld a, [hl] + and a + jr z, .found + add hl, de + dec c + jr nz, .loop + scf + ret + +.found + ld a, [wPikaPicAnimObjectDataBufferSize] + inc a + ld [wPikaPicAnimObjectDataBufferSize], a + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + call GetPikaPicAnimByte + ld [hl], a + xor a + ld [hli], a ; overloads + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + and a + ret + +PikaPicAnimCommand_deleteobject: + call GetPikaPicAnimByte + ld b, a + ld hl, wPikaPicAnimObjectDataBuffer + ld de, 8 + ld c, 4 +.search + ld a, [hl] + cp b + jr z, .delete + add hl, de + dec c + jr nz, .search + scf + ret + +.delete + xor a + ld [hl], a + ret + +LoadPikaPicAnimObjectData: +.loop + ld a, [wCurPikaPicAnimObjectScriptIdx] + cp $23 + jr c, .valid + ld a, $4 +.valid + ld e, a + ld d, 0 + ld hl, PikaPicAnimBGFramesPointers + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wCurPikaPicAnimObjectFrameIdx] + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + cp $e0 + jr z, .end + jr .init + +.end + xor a + ld [wCurPikaPicAnimObjectFrameIdx], a + ld [wCurPikaPicAnimObjectFrameTimer], a + jr .loop + +.init + push hl + call LoadCurPikaPicObjectTilemap + pop hl + ld a, [hl] + and a + jr z, .not_done ; lasts forever + ld a, [wCurPikaPicAnimObjectFrameTimer] + inc a + ld [wCurPikaPicAnimObjectFrameTimer], a + cp [hl] + jr nz, .not_done + xor a + ld [wCurPikaPicAnimObjectFrameTimer], a + ld a, [wCurPikaPicAnimObjectFrameIdx] + inc a + ld [wCurPikaPicAnimObjectFrameIdx], a +.not_done + ret + +INCLUDE "data/pikachu/pikachu_pic_objects.asm" + +LoadCurPikaPicObjectTilemap: + and a + ret z + ld e, a + ld d, 0 + ld hl, PikaPicTilemapPointers + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld a, [de] + ld c, a + inc de + ld a, [de] + ld b, a + inc de + push de + push bc + call .GetStartCoords + pop bc + pop de +.row + push bc + push hl + ld a, [wCurPikaPicAnimObjectVTileOffset] ; tile id offset + ld c, a +.col + ld a, [de] + inc de + cp $ff + jr z, .skip + add c + ld [hl], a +.skip + inc hl + dec b + jr nz, .col + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec c + jr nz, .row + ret + +.GetStartCoords: + push bc + ld a, [wCurPikaPicAnimObjectYOffset] ; Y offset + ld b, a + ld a, [wPikaPicPikaDrawStartY] + add b + hlcoord 0, 0 + ld bc, SCREEN_WIDTH + call AddNTimes + ld a, [wCurPikaPicAnimObjectXOffset] ; X offset + ld c, a + ld a, [wPikaPicPikaDrawStartX] + add c + ld c, a + ld b, 0 + add hl, bc + pop bc + ret + +INCLUDE "data/pikachu/pikachu_pic_tilemaps.asm" + +LoadPikaPicAnimGFXHeader: + push hl + ld e, a + ld d, 0 + ld hl, PikaPicAnimGFXHeaders + add hl, de + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + pop hl + ret + +RunPikaPicAnimSetupScript: + call .CheckAndAdvanceTimer + ret c + xor a + ld [wPikaPicAnimPointerSetupFinished], a +.loop + call GetPikaPicAnimByte + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call JumpToAddress + ld a, [wPikaPicAnimPointerSetupFinished] + and a + jr z, .loop + ret + +.CheckAndAdvanceTimer: + ld a, [wPikaPicAnimDelay] + and a + ret z + dec a + ld [wPikaPicAnimDelay], a + scf + ret + +.Jumptable: + dw PikaPicAnimCommand_nop ; 00, 0 params + dw PikaPicAnimCommand_writebyte ; 01, 1 param + dw PikaPicAnimCommand_loadgfx ; 02, 1 param + dw PikaPicAnimCommand_object ; 03, 5 params + dw PikaPicAnimCommand_nop4 ; 04, 0 params + dw PikaPicAnimCommand_nop5 ; 05, 0 params + dw PikaPicAnimCommand_deleteobject ; 06, 1 param + dw PikaPicAnimCommand_nop7 ; 07, 0 params + dw PikaPicAnimCommand_nop8 ; 08, 0 params + dw PikaPicAnimCommand_jump ; 09, 1 dw param + dw PikaPicAnimCommand_setduration ; 0a, 1 dw param + dw PikaPicAnimCommand_cry ; 0b, 1 param + dw PikaPicAnimCommand_thunderbolt ; 0c, 0 params + dw PikaPicAnimCommand_run ; 0d, 0 params (ret) + dw PikaPicAnimCommand_ret ; 0e, 0 params (ret) + +PikaPicAnimCommand_nop: + ret + +PikaPicAnimCommand_ret: + ld a, 1 + ld [wPikaPicAnimTimer], a + xor a + ld [wPikaPicAnimTimer + 1], a + jr PikaPicAnimCommand_run + +; XXX + ret + +PikaPicAnimCommand_setduration: + call GetPikaPicAnimByte + ld [wPikaPicAnimTimer], a + call GetPikaPicAnimByte + ld [wPikaPicAnimTimer + 1], a + ret + +PikaPicAnimCommand_run: + ld a, $ff + ld [wPikaPicAnimPointerSetupFinished], a + ret + +PikaPicAnimCommand_writebyte: + call GetPikaPicAnimByte + ld [wPikaPicAnimDelay], a + ret + +PikaPicAnimCommand_nop4: +PikaPicAnimCommand_nop5: +PikaPicAnimCommand_nop7: +PikaPicAnimCommand_nop8: + ret + +PikaPicAnimCommand_jump: + call GetPikaPicAnimByte + ld l, a + call GetPikaPicAnimByte + ld h, a + call UpdatePikaPicAnimPointer + ret + +GetPikaPicAnimByte: + push hl + ld hl, wPikaPicAnimPointer + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [hli] + call UpdatePikaPicAnimPointer + pop hl + ret + +UpdatePikaPicAnimPointer: + push af + ld a, l + ld [wPikaPicAnimPointer], a + ld a, h + ld [wPikaPicAnimPointer + 1], a + pop af + ret + +PikaPicAnimCommand_loadgfx: + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + ldh a, [hAutoBGTransferEnabled] + push af + xor a + ldh [hAutoBGTransferEnabled], a + ldh a, [hTilesetType] + push af + xor a + ldh [hTilesetType], a + call GetPikaPicAnimByte + ld [wPikaPicAnimCurGraphicID], a + ld a, [wPikaPicAnimCurGraphicID] + call LoadPikaPicAnimGFXHeader + ld a, c + cp a, $ff + jr z, .compressed + call RequestPikaPicAnimGFX + jr .done + +.compressed + call DecompressRequestPikaPicAnimGFX +.done + pop af + ldh [hTilesetType], a + pop af + ldh [hAutoBGTransferEnabled], a + pop af + ld [wUpdateSpritesEnabled], a + ret + +RequestPikaPicAnimGFX: + push de + ld a, [wPikaPicAnimCurGraphicID] + ld d, a + ld e, c + call CheckIfThereIsRoomForPikaPicAnimGFX + pop de + jr c, .failed + call GetPikaPicVRAMAddressForNewGFX + call CopyVideoDataAlternate + and a +.failed + ret + +DecompressRequestPikaPicAnimGFX: + push de + ld a, [wPikaPicAnimCurGraphicID] + ld d, a + ld e, 5 * 5 + call CheckIfThereIsRoomForPikaPicAnimGFX + pop de + jr c, .failed + ld a, b + call UncompressSpriteFromDE + ld a, BANK(sSpriteBuffer1) + call SwitchSRAMBankAndLatchClockData + ld hl, sSpriteBuffer1 + ld de, sSpriteBuffer0 + ld bc, SPRITEBUFFERSIZE * 2 + call CopyData + call PrepareRTCDataAndDisableSRAM + ld a, [wPikaPicAnimCurGraphicID] + call LookUpTileOffsetForCurrentPikaPicAnimGFX + call GetPikaPicVRAMAddressForNewGFX + ld d, h + ld e, l + call InterlaceMergeSpriteBuffers +.failed + ret + +ClearPikaPicUsedGFXBuffer: + ld hl, wPikaPicUsedGFXCount + ld bc, wPikaPicUsedGFXEnd - wPikaPicUsedGFXCount + xor a + call FillMemory + ret + +GetPikaPicVRAMAddressForNewGFX: + ld hl, vNPCSprites + push bc + ld b, a + and $f + swap a + ld c, a + ld a, b + and $f0 + swap a + ld b, a + add hl, bc + pop bc + ret + +CheckIfThereIsRoomForPikaPicAnimGFX: +; d: idx +; e: size +; FATAL: If the graphic has already been loaded, or if there are +; already 8 graphics objects loaded, the game will execute arbitrary +; code. + push bc + push hl + ld hl, wPikaPicUsedGFX + ld c, 8 +.loop + ld a, [hl] + and a + jr z, .empty + cp d + jr z, .found + inc hl + inc hl + dec c + jr nz, .loop + scf + ret ; execute hl, then bc + +.found + inc hl + ld a, [hl] + ret ; execute hl, then bc + +.empty + ld [hl], d + inc hl + ld a, [wPikaPicUsedGFXCount] + add $80 + ld [hl], a + ld a, [wPikaPicUsedGFXCount] + add e + ld [wPikaPicUsedGFXCount], a + cp $80 + jr z, .okay + jr nc, .failed +.okay + ld a, [hl] + and a + jr .pop_ret + +.failed + scf +.pop_ret + pop hl + pop bc + ret + +LookUpTileOffsetForCurrentPikaPicAnimGFX: + push bc + push hl + ld b, a + ld hl, wPikaPicUsedGFX + ld c, 8 +.loop + ld a, [hli] + cp b + jr z, .found + inc hl + dec c + jr nz, .loop + scf + jr .pop_ret + +.found + ld a, [hl] + and a +.pop_ret + pop hl + pop bc + ret + +PikaPicAnimCommand_cry: + call GetPikaPicAnimByte + cp $ff + ret z + ld e, a + callfar PlayPikachuSoundClip + ret + +PikaPicAnimCommand_thunderbolt: + ld a, $1 + ld [wMuteAudioAndPauseMusic], a + call DelayFrame + ld a, [wAudioROMBank] + push af + ld a, BANK(SFX_Battle_2F) + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + call .LoadAudio + call PlaySound + call .FlashScreen + call WaitForSoundToFinish + pop af + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + xor a + ld [wMuteAudioAndPauseMusic], a + ret + +.LoadAudio: + ld hl, MoveSoundTable + ld e, THUNDERBOLT + ld d, 0 + add hl, de + add hl, de + add hl, de + ld a, BANK(MoveSoundTable) + call GetFarByte + ld b, a + inc hl + ld a, BANK(MoveSoundTable) + call GetFarByte + inc hl + ld [wFrequencyModifier], a + ld a, BANK(MoveSoundTable) + call GetFarByte + ld [wTempoModifier], a + ld a, b + ret + +.FlashScreen: + ld hl, PikaPicAnimThunderboltPals +.loop + ld a, [hli] + cp $ff + ret z + ld c, a + ld b, [hl] + inc hl + push hl + call .UpdatePal + pop hl + jr .loop + +.UpdatePal: + ld a, b + ldh [rBGP], a + call UpdateGBCPal_BGP + call DelayFrames + ret + +INCLUDE "data/pikachu/pikachu_pic_animation.asm" + +Func_fe66e: + ret diff --git a/engine/pikachu/pikachu_status.asm b/engine/pikachu/pikachu_status.asm new file mode 100755 index 00000000..c73d3b3f --- /dev/null +++ b/engine/pikachu/pikachu_status.asm @@ -0,0 +1,258 @@ +IsStarterPikachuInOurParty:: + ld hl, wPartySpecies + ld de, wPartyMon1OTID + ld bc, wPartyMonOT + push hl +.loop + pop hl + ld a, [hli] + push hl + inc a + jr z, .noPlayerPikachu + cp PIKACHU + 1 + jr nz, .curMonNotPlayerPikachu + ld h, d + ld l, e + ld a, [wPlayerID] + cp [hl] + jr nz, .curMonNotPlayerPikachu + inc hl + ld a, [wPlayerID+1] + cp [hl] + jr nz, .curMonNotPlayerPikachu + push de + push bc + ld hl, wPlayerName + ld d, $6 ; possible player length - 1 +.nameCompareLoop + dec d + jr z, .sameOT + ld a, [bc] + inc bc + cp [hl] + inc hl + jr z, .nameCompareLoop + pop bc + pop de +.curMonNotPlayerPikachu + ld hl, wPartyMon2 - wPartyMon1 + add hl, de + ld d, h + ld e, l + ld hl, NAME_LENGTH + add hl, bc + ld b, h + ld c, l + jr .loop + +.sameOT + pop bc + pop de + ld h, d + ld l, e + ld bc, -NAME_LENGTH + add hl, bc + ld a, [hli] + or [hl] + jr z, .noPlayerPikachu ; XXX how is this determined? + pop hl + scf + ret + +.noPlayerPikachu + pop hl + and a + ret + +IsThisPartymonStarterPikachu_Box:: + ld hl, wBoxMon1 + ld bc, wBoxMon2 - wBoxMon1 + ld de, wBoxMonOT + jr asm_fce21 + +IsThisPartymonStarterPikachu_Party:: +IsThisPartymonStarterPikachu:: + ld hl, wPartyMon1 + ld bc, wPartyMon2 - wPartyMon1 + ld de, wPartyMonOT +asm_fce21: + ld a, [wWhichPokemon] + call AddNTimes + ld a, [hl] + cp PIKACHU + jr nz, .notPlayerPikachu + ld bc, wPartyMon1OTID - wPartyMon1 + add hl, bc + ld a, [wPlayerID] + cp [hl] + jr nz, .notPlayerPikachu + inc hl + ld a, [wPlayerID+1] + cp [hl] + jr nz, .notPlayerPikachu + ld h, d + ld l, e + ld a, [wWhichPokemon] + ld bc, NAME_LENGTH + call AddNTimes + ld de, wPlayerName + ld b, $6 +.loop + dec b + jr z, .isPlayerPikachu + ld a, [de] + inc de + cp [hl] + inc hl + jr z, .loop +.notPlayerPikachu + and a + ret + +.isPlayerPikachu + scf + ret + +UpdatePikachuMoodAfterBattle:: +; because d is always $82 at this function, it serves to +; ensure Pikachu's mood is at least 130 after battle + push de + call IsStarterPikachuInOurParty + pop de + ret nc + ld a, d + cp 128 + ld a, [wPikachuMood] + jr c, .d_less_than_128 ; we never jump + cp d + jr c, .load_d_into_mood + ret + +.d_less_than_128 + cp d + ret c +.load_d_into_mood + ld a, d + ld [wPikachuMood], a + ret + +CheckPikachuFaintedOrStatused:: +; function to test if Pikachu is alive? + xor a + ld [wWhichPokemon], a + ld hl, wPartyCount +.loop + inc hl + ld a, [hl] + cp $ff + jr z, .dead_or_not_in_party + push hl + call IsThisPartymonStarterPikachu_Party + pop hl + jr nc, .next + ld a, [wWhichPokemon] + ld hl, wPartyMon1HP + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hli] + or [hl] + ld d, a + inc hl + inc hl + ld a, [hl] ; status + and a + jr nz, .alive + jr .dead_or_not_in_party + +.next + ld a, [wWhichPokemon] + inc a + ld [wWhichPokemon], a + jr .loop + +.alive + scf + ret + +.dead_or_not_in_party + and a + ret + +IsSurfingPikachuInThePlayersParty:: + ld hl, wPartySpecies + ld de, wPartyMon1Moves + ld bc, wPartyMonOT + push hl +.loop + pop hl + ld a, [hli] + push hl + inc a + jr z, .noSurfingPlayerPikachu + cp PIKACHU+1 + jr nz, .curMonNotSurfingPlayerPikachu + ld h, d + ld l, e + push hl + push bc + ld b, NUM_MOVES +.moveSearchLoop + ld a, [hli] + cp SURF + jr z, .foundSurfingPikachu + dec b + jr nz, .moveSearchLoop + pop bc + pop hl + jr .curMonNotSurfingPlayerPikachu + +.foundSurfingPikachu + pop bc + pop hl + inc hl + inc hl + inc hl + inc hl + ld a, [wPlayerID] + cp [hl] + jr nz, .curMonNotSurfingPlayerPikachu + inc hl + ld a, [wPlayerID+1] + cp [hl] + jr nz, .curMonNotSurfingPlayerPikachu + push de + push bc + ld hl, wPlayerName + ld d, $6 +.nameCompareLoop + dec d + jr z, .foundSurfingPlayerPikachu + ld a, [bc] + inc bc + cp [hl] + inc hl + jr z, .nameCompareLoop + pop bc + pop de +.curMonNotSurfingPlayerPikachu + ld hl, wPartyMon2 - wPartyMon1 + add hl, de + ld d, h + ld e, l + ld hl, NAME_LENGTH + add hl, bc + ld b, h + ld c, l + jr .loop + +.foundSurfingPlayerPikachu + pop bc + pop de + pop hl + scf + ret + +.noSurfingPlayerPikachu + pop hl + and a + ret diff --git a/engine/pikachu/respawn_overworld_pikachu.asm b/engine/pikachu/respawn_overworld_pikachu.asm new file mode 100644 index 00000000..4b610085 --- /dev/null +++ b/engine/pikachu/respawn_overworld_pikachu.asm @@ -0,0 +1,6 @@ +RespawnOverworldPikachu: + callfar IsThisPartymonStarterPikachu_Party + ret nc + ld a, $3 + ld [wPikachuSpawnState], a + ret |