summaryrefslogtreecommitdiff
path: root/engine/bank3d.asm
diff options
context:
space:
mode:
Diffstat (limited to 'engine/bank3d.asm')
-rw-r--r--engine/bank3d.asm697
1 files changed, 697 insertions, 0 deletions
diff --git a/engine/bank3d.asm b/engine/bank3d.asm
new file mode 100644
index 00000000..6efff351
--- /dev/null
+++ b/engine/bank3d.asm
@@ -0,0 +1,697 @@
+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"
+
+StarterPikachuBattleEntranceAnimation:
+ coord hl, 0, 5
+ ld c, 0
+.loop1
+ inc c
+ ld a, c
+ cp 9
+ ret z
+ ld d, 7 * 13
+ push bc
+ push hl
+.loop2
+ call .PlaceColumn
+ dec hl
+ ld a, d
+ sub 7
+ ld d, a
+ dec c
+ jr nz, .loop2
+ ld c, 2
+ call DelayFrames
+ pop hl
+ pop bc
+ inc hl
+ jr .loop1
+
+.PlaceColumn:
+ push hl
+ push de
+ push bc
+ ld e, 7
+.loop3
+ ld a, d
+ cp 7 * 7
+ jr nc, .okay
+ ld a, $7f
+.okay
+ ld [hl], a
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ inc d
+ dec e
+ jr nz, .loop3
+ pop bc
+ pop de
+ pop hl
+ ret
+
+INCLUDE "engine/battle/decrement_pp.asm"
+
+ModifyPikachuHappiness::
+ 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:
+ ; 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:
+ ; 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"
+
+LoadYellowTitleScreenGFX:
+ ld hl, PokemonLogoGraphics
+ ld de, vChars2
+ ld bc, 115 * $10
+ ld a, BANK(PokemonLogoGraphics) ; redundant because this function is in bank3d
+ call FarCopyData
+ ld hl, YellowLogoGraphics + 35 * $10
+ ld de, vChars0 + 253 * $10
+ ld bc, 3 * $10
+ ld a, BANK(YellowLogoGraphics)
+ call FarCopyData
+ ld hl, YellowLogoGraphics + 38 * $10
+ ld de, vChars1
+ ld bc, 64 * $10
+ ld a, BANK(YellowLogoGraphics)
+ call FarCopyData
+ ld hl, YellowLogoGraphics + 102 * $10
+ ld de, vChars0 + 240 * $10
+ ld bc, 12 * $10
+ ld a, BANK(YellowLogoGraphics)
+ call FarCopyData
+ ret
+
+TitleScreen_PlacePokemonLogo:
+ coord hl, 2, 1
+ ld de, TitleScreenPokemonLogoTilemap
+ lb bc, 7, 16
+ call Bank3D_CopyBox
+ ret
+
+TitleScreen_PlacePikaSpeechBubble:
+ coord hl, 6, 4
+ ld de, TitleScreenPikaBubbleTilemap
+ lb bc, 4, 7
+ call Bank3D_CopyBox
+ coord hl, 9, 8
+ ld [hl], $64
+ inc hl
+ ld [hl], $65
+ ret
+
+TitleScreen_PlacePikachu:
+ coord hl, 4, 8
+ ld de, TitleScreenPikachuTilemap
+ lb bc, 9, 12
+ call Bank3D_CopyBox
+ 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, TitleScreenPikachuEyesOAMData
+ ld de, wOAMBuffer
+ ld bc, $20
+ call CopyData
+ ret
+
+TitleScreenPikachuEyesOAMData:
+ 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
+
+Bank3D_CopyBox:
+; copy cxb (xy) screen area from de to hl
+.row
+ push bc
+ push hl
+.col
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+
+TitleScreenPokemonLogoTilemap:
+; 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:
+; Unreferenced
+ db $47, $48, $49, $4a, $4b, $4c, $4d, $4e, $4f, $5f
+
+TitleScreenPikaBubbleTilemap:
+; 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
+
+TitleScreenPikachuTilemap:
+; 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"
+PokemonLogoGraphicsEnd:
+YellowLogoGraphics: INCBIN "gfx/yellow_titlescreen.2bpp"
+YellowLogoGraphicsEnd:
+
+INCLUDE "engine/menu/link_menu.asm"
+
+HandleMenuInputDouble:
+ xor a
+ ld [wPartyMenuAnimMonEnabled], a
+
+HandleMenuInputPokemonSelectionDouble:
+ 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 .UpdateCursorTile
+ 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, SFX_PRESS_AB
+ call PlaySound ; play sound
+.skipPlayingSound
+ pop af
+ ld [H_DOWNARROWBLINKCNT2], a
+ pop af
+ ld [H_DOWNARROWBLINKCNT1], a ; restore previous values
+ ld a, [hJoy5]
+ ret
+
+.UpdateCursorTile:
+ ld a, [wTopMenuItemY]
+ and a
+ jr z, .asm_f5ac0
+ coord hl, 0, 0
+ ld bc, SCREEN_WIDTH
+.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
+
+PrintStrengthTxt:
+ ld hl, wd728
+ set 0, [hl]
+ ld hl, Text_f5b17
+ call PrintText
+ ld hl, Text_f5b28
+ jp PrintText
+
+Text_f5b17:
+ TX_FAR _UsedStrengthText ; 2d:417e
+ TX_ASM
+ ld a, [wcf91]
+ call PlayCry
+ call Delay3
+ jp TextScriptEnd
+
+Text_f5b28:
+ TX_FAR _CanMoveBouldersText ; 2d:4193
+ db "@"
+
+IsSurfingAllowed:
+; Returns whether surfing is allowed in bit 1 of wd728.
+; Surfing isn't allowed on the Cycling Road or in the lowest level of the
+; Seafoam Islands before the current has been slowed with boulders.
+ ld hl, wd728
+ set 1, [hl]
+ ld a, [wd732]
+ bit 5, a
+ jr nz, .forcedToRideBike
+ 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
+.forcedToRideBike
+ ld hl, wd728
+ res 1, [hl]
+ ld hl, CyclingIsFunText
+ jp PrintText
+
+CoordsData_f5b64:
+ db 11, 07
+ db $ff
+
+CurrentTooFastText:
+ TX_FAR _CurrentTooFastText ; 2d:41ab
+ db "@"
+
+CyclingIsFunText:
+ TX_FAR _CyclingIsFunText ; 2d:41ca
+ db "@"
+
+AddItemToInventory_:
+ ld a, [wItemQuantity] ; a = item quantity
+ push af
+ push bc
+ push de
+ push hl
+ push hl
+ ld d, PC_ITEM_CAPACITY ; how many items the PC can hold
+ 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, BAG_ITEM_CAPACITY ; how many items the bag can hold
+.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_:
+ 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:
+ 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:
+ 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"