INCLUDE "engine/battle/common_text.asm" INCLUDE "engine/battle/link_battle_versus_text.asm" INCLUDE "engine/battle/unused_stats_functions.asm" INCLUDE "engine/battle/scroll_draw_trainer_pic.asm" Func_f429f:: ; f429f (3d:429f) coord hl, 0,5 ld c,$0 .asm_f42a4 inc c ld a,c cp $9 ret z ld d,$5b push bc push hl .asm_f42ad call Func_f42c2 dec hl ld a,d sub $7 ld d,a dec c jr nz,.asm_f42ad ld c,$2 call DelayFrames pop hl pop bc inc hl jr .asm_f42a4 Func_f42c2:: ; f42c2 (3d:f42c2) push hl push de push bc ld e,$7 .loop ld a,d cp $31 jr nc,.asm_f42ce ld a,$7f .asm_f42ce ld [hl],a ld bc,$14 add hl,bc inc d dec e jr nz,.loop pop bc pop de pop hl ret INCLUDE "engine/battle/decrement_pp.asm" ModifyPikachuHappiness:: ; f430a (3d:430a) ld a, d cp PIKAHAPPY_GYMLEADER jr z, .checkanywhereinparty cp PIKAHAPPY_WALKING jr z, .checkanywhereinparty push de callab IsThisPartymonStarterPikachu_Party pop de ret nc jr .proceed .checkanywhereinparty push de callab IsStarterPikachuInOurParty pop de ret nc .proceed push de ; Divide [wPikachuHappiness] by 100. Hold the integer part in e. ld e, $0 ld a, [wPikachuHappiness] cp 100 jr c, .wPikachuHappiness_div_100 inc e cp 200 jr c, .wPikachuHappiness_div_100 inc e .wPikachuHappiness_div_100 ; Get the (d, e) entry from HappinessChangeTable. ld c, d dec c ld b, $0 ld hl, HappinessChangeTable add hl, bc add hl, bc add hl, bc ld d, $0 add hl, de ld a, [hl] ; If [hl] is positive, take min(0xff, [hl] + [wPikachuHappiness]). ; If [hl] is negative, take max(0x00, [hl] + [wPikachuHappiness]). ; Inexplicably, we're using 100 as the threshold for comparison. cp 100 ld a, [wPikachuHappiness] jr nc, .negative add [hl] jr nc, .okay ld a, -1 jr .okay .negative add [hl] jr c, .okay xor a .okay ld [wPikachuHappiness], a ; Restore d and get the d'th entry in PikachuMoods. pop de dec d ld hl, PikachuMoods ld e, d ld d, $0 add hl, de ld a, [hl] ld b, a ; Modify Pikachu's mood cp $80 jr z, .done ld a, [wPikachuMood] jr c, .decreased cp b jr nc, .done ld a, [wd49c] and a jr nz, .done jr .update_mood .decreased cp b jr c, .done .update_mood ld a, b ld [wPikachuMood], a .done ret HappinessChangeTable: ; f4385 (3d:4385) ; Increase db 5, 3, 2 ; Gained a level db 5, 3, 2 ; HP restore db 1, 1, 0 ; Used X item db 3, 2, 1 ; Challenged Gym Leader db 1, 1, 0 ; Teach TM/HM db 2, 1, 1 ; Walking around ; Decrease db -3, -3, -5 ; Deposited db -1, -1, -1 ; Fainted in battle db -5, -5, -10 ; Fainted due to Poison outside of battle db -5, -5, -10 ; Unknown (d = 10) db -10, -10, -20 ; Unknown (d = 11) PikachuMoods: ; f43a6 (3d:43a6) ; Increase db $8a ; Gained a level db $83 ; HP restore db $80 ; Teach TM/HM db $80 ; Challenged Gym Leader db $94 ; Unknown (d = 5) db $80 ; Unknown (d = 6) ; Decrease db $62 ; Deposited db $6c ; Fainted db $62 ; Unknown (d = 9) db $6c ; Unknown (d = 10) db $00 ; Unknown (d = 11) RedPicBack:: INCBIN "pic/trainer/redb.pic" OldManPic:: INCBIN "pic/trainer/oldman.pic" ProfOakPicBack:: INCBIN "pic/ytrainer/prof.oakb.pic" Func_f453f:: ; f453f (3d:453f) ld hl,PokemonLogoGraphics ld de,vChars2 ld bc,$730 ld a,BANK(PokemonLogoGraphics) ; redundant because this function is in bank3d call FarCopyData ld hl,YellowLogoGraphics+$230 ld de,vChars0+$fd0 ld bc,$30 ld a,BANK(YellowLogoGraphics) call FarCopyData ld hl,YellowLogoGraphics+$260 ld de,vChars1 ld bc,$400 ld a,BANK(YellowLogoGraphics) call FarCopyData ld hl,YellowLogoGraphics+$660 ld de,vChars0+$f00 ld bc,$c0 ld a,BANK(YellowLogoGraphics) call FarCopyData ret Func_f4578:: ; f4578 (3d:4578) coord hl, 2,1 ld de,Pointer_f45f9 ld bc,7 << 8 | 16 ; 16x7 (xy) call CopyScreenArea ret Func_f4585:: ; f4585 (3d:4585) coord hl, 6,4 ld de,Pointer_f4673 ld bc,4 << 8 | 7 ; 7x4 (xy) call CopyScreenArea coord hl, 9,8 ld [hl],$64 inc hl ld [hl],$65 ret Func_f459a:: ; f459a (3d:459a) coord hl, 4,8 ld de,Pointer_f468f ld bc,9 << 8 | 12 ; 12x9 (xy) call CopyScreenArea coord hl, 16,10 ld [hl],$96 coord hl, 16,11 ld [hl],$9d coord hl, 16,12 ld [hl],$a7 coord hl, 16,13 ld [hl],$b1 ld hl,Pointer_f45c7 ld de,wOAMBuffer ld bc,$20 call CopyData ret Pointer_f45c7: ; f45c7 (3d:45c7) db $60,$40,$f1,$22 db $60,$48,$f0,$22 db $68,$40,$f3,$22 db $68,$48,$f2,$22 db $60,$60,$f0,$02 db $60,$68,$f1,$02 db $68,$60,$f2,$02 db $68,$68,$f3,$02 CopyScreenArea:: ; f45e7 (3d:45e7) ; copy cxb (xy) screen area from de to hl push bc push hl .loop ld a,[de] inc de ld [hli],a dec c jr nz,.loop pop hl ld bc,$14 add hl,bc pop bc dec b jr nz,CopyScreenArea ret Pointer_f45f9: ; f45f9 (3d:45f9) ; 16x7 (xy) db $f4,$f4,$f4,$f4,$f4,$f4,$49,$f4,$72,$30,$f4,$f4,$f4,$f4,$f4,$f4 db $fd,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a,$0b,$f4,$0d,$0e,$0f db $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1a,$1b,$1c,$1d,$1e,$1f db $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f db $f4,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f db $f4,$41,$42,$43,$44,$45,$46,$47,$48,$f4,$4a,$4b,$4c,$4d,$4e,$4f db $f4,$6a,$6b,$6c,$6d,$f4,$f4,$f4,$f4,$f4,$f4,$6e,$6f,$70,$71,$f4 Pointer_f4669:: ; f4669 (3d:4669) db $47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f,$5f Pointer_f4673:: ; f4673 (3d:4673) ; 7x4 (xy) db $24,$25,$66,$67,$68,$69,$2a db $50,$51,$52,$53,$54,$55,$56 db $57,$58,$59,$5a,$5b,$5c,$5d db $6d,$5e,$5f,$60,$61,$62,$63 Pointer_f468f:: ; f468f (3d:468f) ; 12x9 (xy) db $80,$81,$82,$83,$00,$00,$00,$00,$84,$85,$86,$87 db $88,$89,$8a,$8b,$8c,$8d,$8d,$8e,$8f,$8a,$90,$91 db $00,$92,$93,$8a,$8a,$8a,$8a,$8a,$8a,$94,$95,$00 db $00,$00,$97,$8a,$8a,$98,$99,$8a,$8a,$9a,$9b,$9c db $00,$00,$9e,$9f,$a0,$a1,$a2,$a3,$a4,$a5,$a6,$8a db $00,$a8,$a9,$aa,$8a,$ab,$ac,$8a,$ad,$ae,$af,$b0 db $00,$b2,$b3,$b4,$8a,$8a,$8a,$8a,$b5,$b6,$b7,$b8 db $00,$b9,$ba,$8a,$8a,$8a,$8a,$8a,$8a,$bb,$bc,$00 db $00,$00,$bd,$8a,$8a,$8a,$8a,$8a,$8a,$be,$bf,$00 ; f46f9 (3d:46f9) PokemonLogoGraphics: INCBIN "gfx/pokemon_logo.2bpp" YellowLogoGraphics: INCBIN "gfx/yellow_titlescreen.2bpp" INCLUDE "engine/menu/link_menu.asm" HandleMenuInputDouble:: ; f5a40 (3d:5a40) xor a ld [wPartyMenuAnimMonEnabled],a HandleMenuInputPokemonSelectionDouble:: ; f5a44 (3d:5a44) 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 [wAnimCounter],a ; counter for pokemon shaking animation call Func_f5ab0 call JoypadLowSensitivity ld a,[hJoy5] and a ; was a key pressed? jr nz,.keyPressed 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 [wCheckFor180DegreeTurn],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,.checkOtherKeys .notAtTop dec a ld [wCurrentMenuItem],a ; move selected menu item up one space jr .checkOtherKeys .checkIfDownPressed bit 7,a jr z,.checkOtherKeys .downPressed ld a,[wCurrentMenuItem] inc a ld c,a ld a,[wMaxMenuItem] cp c jr c,.checkOtherKeys 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 ld a, $90 ; (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 ld a,[hJoy5] ret Func_f5ab0:: ; f5ab0 (3d:5ab0) ld a,[wTopMenuItemY] and a jr z,.asm_f5ac0 coord hl, 0,0 ld bc,$14 .loop add hl,bc dec a jr nz,.loop .asm_f5ac0 ld a,[wTopMenuItemX] ld b,$0 ld c,a add hl,bc push hl ld a,[wLastMenuItem] and a jr z,.asm_f5ad5 ld bc,$28 .loop2 add hl,bc dec a jr nz,.loop2 .asm_f5ad5 ld a,[hl] cp "▶" jr nz,.asm_f5ade ld a,[wTileBehindCursor] ld [hl],a .asm_f5ade pop hl ld a,[wCurrentMenuItem] and a jr z,.asm_f5aec ld bc,$28 .loop3 add hl,bc dec a jr nz,.loop3 .asm_f5aec ld a,[hl] cp "▶" jr z,.asm_f5af4 ld [wTileBehindCursor],a .asm_f5af4 ld a,"▶" ld [hl],a ld a,l ld [wMenuCursorLocation],a ld a,h ld [wMenuCursorLocation+1],a ld a,[wCurrentMenuItem] ld [wLastMenuItem],a ret Func_f5b06:: ; f5b06 (3d:5b06) ld hl,wd728 set 0,[hl] ld hl,Text_f5b17 call PrintText ld hl,Text_f5b28 jp PrintText Text_f5b17:: ; f5b17 (3d:5b17) TX_FAR _UsedStrengthText ; 2d:417e db $08 ; asm ld a,[wcf91] call PlayCry call Delay3 jp TextScriptEnd Text_f5b28:: ; f5b28 (3d:5b28) TX_FAR _CanMoveBouldersText ; 2d:4193 db "@" CheckForForcedBikeSurf:: ; f5b2d (3d:5b2d) ld hl,wd728 set 1,[hl] ld a,[wd732] bit 5,a jr nz,.asm_f5b59 ld a,[wCurMap] cp SEAFOAM_ISLANDS_5 ret nz CheckBothEventsSet EVENT_SEAFOAM4_BOULDER1_DOWN_HOLE, EVENT_SEAFOAM4_BOULDER2_DOWN_HOLE ret z ld hl,CoordsData_f5b64 call ArePlayerCoordsInArray ret nc ld hl,wd728 res 1,[hl] ld hl,CurrentTooFastText jp PrintText .asm_f5b59 ld hl,wd728 res 1,[hl] ld hl,CyclingIsFunText jp PrintText CoordsData_f5b64:: ; f5b64 (3d:5b64) db 11,07 db $ff CurrentTooFastText:: ; f5b67 (3d:5b67) TX_FAR _CurrentTooFastText ; 2d:41ab db "@" CyclingIsFunText:: ; f5b6c (3d:5b6c) TX_FAR _CyclingIsFunText ; 2d:41ca db "@" AddItemToInventory_:: ; f5b70 (3d:5b70) ld a,[wItemQuantity] ; 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 .notAtEndOfInventory 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 .loop ld a,[hl] cp a,$ff ; is it the end of the table? jr nz, .notAtEndOfInventory .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,[wItemQuantity] 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,[wItemQuantity] 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 [wItemQuantity],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 [wItemQuantity],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 ; [wItemQuantity] = quantity to remove RemoveItemFromInventory_: ; f5be1 (3d:5be1) push hl inc hl ld a,[wWhichPokemon] ; index (within the inventory) of the item being removed add a add l ld l,a jr nc,.noCarry inc h .noCarry inc hl ld a,[wItemQuantity] ; quantity being removed ld e,a ld a,[hl] ; a = current quantity sub e ld [hld],a ; store new quantity ld [wMaxItemQuantity],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 [wBagSavedMenuItem],a ld [wSavedListScrollOffset],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 [wListCount],a cp a,2 jr c,.done ld [wMaxMenuItem],a jr .done .skipMovingUpSlots pop hl .done ret TrainerInfoTextBoxTileGraphics: INCBIN "gfx/trainer_info.2bpp" TrainerInfoTextBoxTileGraphicsEnd: BlankLeaderNames: INCBIN "gfx/blank_leader_names.2bpp" CircleTile: INCBIN "gfx/circle_tile.2bpp" BadgeNumbersTileGraphics: INCBIN "gfx/badge_numbers.2bpp" ReadSuperRodData:: ; f5ea4 (3d:5ea4) ld a,[wCurMap] ld c,a ld hl,FishingSlots .loop ld a,[hli] cp $ff jr z,.notfound cp c jr z,.found ld de,$8 add hl,de jr .loop .found call GenerateRandomFishingEncounter ret .notfound ld de,$0 ret GenerateRandomFishingEncounter: ; f5ec1 (3d:5ec1) call Random cp $66 jr c,.asm_f5ed6 inc hl inc hl cp $b2 jr c,.asm_f5ed6 inc hl inc hl cp $e5 jr c,.asm_f5ed6 inc hl inc hl .asm_f5ed6 ld e,[hl] inc hl ld d,[hl] ret INCLUDE "data/super_rod.asm" INCLUDE "engine/battle/bank3d_battle.asm" INCLUDE "engine/items/tm_prices.asm" INCLUDE "engine/multiply_divide.asm" INCLUDE "engine/give_pokemon.asm" INCLUDE "engine/battle/get_trainer_name.asm" INCLUDE "engine/random.asm" INCLUDE "engine/predefs.asm"