summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engine')
-rwxr-xr-xengine/bcd.asm55
-rwxr-xr-xengine/events/overworld.asm510
-rwxr-xr-xengine/items/inventory.asm48
-rwxr-xr-xengine/items/item_effects.asm79
-rwxr-xr-xengine/overworld/spawn_points.asm4
-rwxr-xr-xengine/pokemon/health.asm359
6 files changed, 1028 insertions, 27 deletions
diff --git a/engine/bcd.asm b/engine/bcd.asm
new file mode 100755
index 0000000..53f0b20
--- /dev/null
+++ b/engine/bcd.asm
@@ -0,0 +1,55 @@
+INCLUDE "constants.asm"
+
+SECTION "BCD", ROMX[$4de3], BANK[$03]
+
+AddBCD: ; 03:4de3
+ and a
+ ld b, c
+.add
+ ld a, [de]
+ adc [hl]
+ daa
+ ld [de], a
+ dec de
+ dec hl
+ dec c
+ jr nz, .add
+ jr nc, .done
+
+ ld a, $99
+ inc de
+
+.fill
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .fill
+
+.done
+ ret
+
+
+SubBCD: ; 03:4df9
+ and a
+ ld b, c
+.sub
+ ld a, [de]
+ sbc [hl]
+ daa
+ ld [de], a
+ dec de
+ dec hl
+ dec c
+ jr nz, .sub
+ jr nc, .done
+ ld a, 0
+ inc de
+
+.fill
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .fill
+ scf
+.done
+ ret \ No newline at end of file
diff --git a/engine/events/overworld.asm b/engine/events/overworld.asm
index a5b4553..0a6eaef 100755
--- a/engine/events/overworld.asm
+++ b/engine/events/overworld.asm
@@ -1,16 +1,478 @@
INCLUDE "constants.asm"
-SECTION "TeleportFunction", ROMX[$52db], BANK[$03]
+SECTION "CutFunction", ROMX[$4fab], BANK[$03]
+
+CutFunction: ; 03:4fab
+ call .reset
+.loop
+ call .next
+ jr nc, .loop
+ ld [wFieldMoveSucceeded], a
+ ret
+.reset
+ xor a
+ ld [wFieldMoveScriptID], a
+ ret
+.next
+ ld a, [wFieldMoveScriptID]
+ ld hl, CutTable
+ jp CallJumptable
+
+CutTable
+ dw TryCut
+ dw CheckMapForSomethingToCut
+ dw CheckMapForSomethingToCut2
+ dw DoCut
+ dw DoCut
+ dw FailCut
+
+TryCut: ; 03:4fd1
+ call GetMapEnvironment
+ cp ROUTE
+ jr z, .success
+ cp TOWN
+ jr z, .success
+ ld a, SCRIPT_ID_05
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+.success
+ ld a, SCRIPT_ID_01
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+
+CheckMapForSomethingToCut: ; 03:4fea
+ call GetFacingTileCoord
+ cp $80 ; TODO - Constant
+ jr nz, .fail
+ call GetBlockLocation
+ ld a, l
+ ld [wMapBlocksAddress], a
+ ld a, h
+ ld [wMapBlocksAddress + 1], a
+ ld a, [hl]
+ call GetCutReplacementBlock
+ jr nc, .fail
+ dec hl
+ ld a, [hl]
+ ld [wReplacementBlock], a
+ ld a, SCRIPT_ID_04
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+.fail
+ ld a, SCRIPT_ID_02
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+
+GetCutReplacementBlock:
+ ld c, a
+ ld hl, CutReplacementBlocks
+.loop
+ ld a, [hli]
+ cp -1
+ ret z
+ inc hl
+ cp c
+ jr nz, .loop
+ scf
+ ret
+
+CutReplacementBlocks:
+; replacement block, facing block
+ db $30, $25
+ db $31, $2A
+ db $32, $34
+ db $33, $35
+ db -1
+
+; TODO - Better name
+CheckMapForSomethingToCut2: ; 03:502c
+ call GetFacingTileCoord
+ call CheckCuttableTile
+ jr nc, .fail
+ call GetBlockLocation
+ ld a, [hl]
+ cp $3b ; TODO - constant?
+ jr nz, .fail
+ ld a, l
+ ld [wMapBlocksAddress], a
+ ld a, h
+ ld [wMapBlocksAddress + 1], a
+ ld a, $04
+ ld [wReplacementBlock], a
+ ld a, SCRIPT_ID_03
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+.fail
+ ld a, SCRIPT_ID_05
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+
+CheckCuttableTile:
+ ld hl, CuttableTiles
+ ld c, a
+.loop
+ ld a, [hli]
+ cp -1
+ ret z
+ cp c
+ jr nz, .loop
+ scf
+ ret
+
+CuttableTiles:
+ db $81
+ db $82
+ db $8A
+ db $8B
+ db -1
+
+FailCut: ; 03:5069
+ ld hl, Text_CantUseCutHere
+ call MenuTextBoxBackup
+ scf
+ ld a, SCRIPT_FAIL
+ ret
+
+Text_CantUseCutHere: ; 03:5073
+ text "ここでは つかえません"
+ prompt
+
+DoCut: ; 03:5080
+ ld hl, CutScript
+ ld a, BANK(CutScript)
+ call QueueScript
+ scf
+ ld a, SCRIPT_SUCCESS
+ ret
+
+CutScript: ; 03:508C
+ call RefreshScreen
+ ld hl, wPartyMonNicknames
+ ld a, 2 ; TODO - constant
+ ld [wMonType], a
+ ld a, [wWhichPokemon]
+ call GetNick
+ call CopyStringToStringBuffer2
+ ld hl, Text_CutItDown
+ call MenuTextBoxBackup
+ ld de, $62 ; TODO - constant
+ call PlaySFX
+ ld hl, wMapBlocksAddress
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [wReplacementBlock]
+ ld [hl], a
+ call LoadMapPart
+ call UpdateSprites
+ call WaitBGMap
+ call Function1fea
+ scf
+ ret
+
+Text_CutItDown: ; 03:50c4
+ text_from_ram wStringBuffer2
+ text " は "
+ line "くさかりを つかった!"
+ prompt
+
+SurfFunction: ; 03:50d8
+ call .reset
+.loop
+ call .next
+ jr nc, .loop
+ ld [wFieldMoveSucceeded], a
+ ret
+.reset
+ xor a
+ ld [wFieldMoveScriptID], a
+ ret
+.next
+ ld a, [wFieldMoveScriptID]
+ ld hl, SurfTable
+ jp CallJumptable
+
+SurfTable:
+ dw TrySurf
+ dw DoSurf
+ dw FailSurf
+
+TrySurf: ; 03:50f8
+ call GetFacingTileCoord
+ and $f0 ; todo - mask constant
+ cp $20 ; todo -constant
+ jr z, .success
+ cp $40 ; todo - constant
+ jr z, .success
+ ld a, SCRIPT_ID_02
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+.success
+ ld a, SCRIPT_ID_01
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+
+DoSurf: ; 03:5113
+ ldh a, [hROMBank]
+ ld hl, SurfScript
+ call QueueScript
+ ld a, SCRIPT_FINISHED
+ ld [wFieldMoveScriptID], a
+ scf
+ ld a, SCRIPT_SUCCESS
+ ret
+
+FailSurf: ; 03:5124
+ ld hl, Text_CantSurfHere
+ call MenuTextBoxBackup
+ ld a, SCRIPT_FINISHED
+ ld [wFieldMoveScriptID], a
+ scf
+ ld a, SCRIPT_FAIL
+ ret
+
+Text_CantSurfHere: ; 03:5133
+ text "ここでは のることが"
+ next "できません"
+ prompt
+
+SurfScript: ; 03:5145
+ call RefreshScreen
+ ld hl, wPartyMonNicknames
+ ld a, 2 ; TODO - constant
+ ld [wMonType], a
+ ld a, [wWhichPokemon]
+ call GetNick
+ call CopyStringToStringBuffer2
+ ld hl, Text_UsedSurf
+ call MenuTextBoxBackup
+ ld a, $04 ; TODO - constant
+ ld [wPlayerBikeSurfState], a
+ call Function0d02
+ call PlayMapMusic
+ call Function_d185
+ call Function1fea
+ ret
+
+Text_UsedSurf: ; 03:5171
+ text_from_ram wStringBuffer2
+ text " は "
+ line "@"
+ text_from_ram wPlayerName
+ text "を のせた!"
+ prompt
+
+Function_d185: ; 03:5185
+ call InitMovementBuffer
+ call .sub_d19b
+ call AppendToMovementBuffer
+ ld a, $32 ; TODO - constant
+ call AppendToMovementBuffer
+ ld a, 0 ; TODO - constant
+ ld hl, wMovementBuffer
+ call LoadMovementDataPointer
+.sub_d19b
+ ld a, [wPlayerWalking]
+ srl a
+ srl a
+ ld e, a
+ ld d, $00
+ ld hl, Table_Unknown_d1ab
+ add hl, de
+ ld a, [hl]
+ ret
+
+Table_Unknown_d1ab:
+ db 4, 5, 6, 7
; Sets wFieldMoveSucceeded to $f if successful, $0 if not
+FlyFunction: ; 03:51af
+ call .reset
+.loop
+ call .next
+ jr nc, .loop
+ ld [wFieldMoveSucceeded], a
+ ret
+.reset
+ xor a
+ ld [wFieldMoveScriptID], a
+ ret
+.next
+ ld a, [wFieldMoveScriptID]
+ ld hl, FlyTable
+ jp CallJumptable
+
+FlyTable: ; 03:51c9
+ dw TryFly
+ dw ShowFlyMap
+ dw DoFly
+ dw FailFly
+
+TryFly: ; 03:51d1
+ call GetMapEnvironment
+ cp TOWN
+ jr z, .success
+ cp ROUTE
+ jr z, .success
+ ld a, SCRIPT_ID_03
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+.success
+ ld a, SCRIPT_ID_01
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+
+ShowFlyMap: ; 03:51ea
+ call LoadStandardMenuHeader
+ call ClearSprites
+ callab FlyMap
+ call ClearPalettes
+ call GetMemSGBLayout
+ call ExitMenu
+ ld a, [wFlyDestination]
+ cp -1
+ jr z, .dont_fly
+ cp NUM_SPAWNS
+ jr nc, .dont_fly
+ ld a, SCRIPT_ID_02
+ ld [wFieldMoveScriptID], a
+ xor a
+ ret
+
+.dont_fly ; 03:5213
+ call UpdateTimePals
+ ld a, SCRIPT_FINISHED
+ ld [wFieldMoveScriptID], a
+ scf
+ ld a, SCRIPT_FAIL
+ ret
+
+DoFly: ; 03:521f
+ ld a, [wFlyDestination]
+ inc a
+ ld [wDefaultSpawnPoint], a
+ ldh a, [hROMBank]
+ ld hl, FlyScript
+ call QueueScript
+ ld a, -1
+ ld [wFieldMoveScriptID], a
+ scf
+ ld a, SCRIPT_SUCCESS
+ ret
+
+FailFly: ; 03:5237
+ ld hl, Text_CantUseFlyHere
+ call MenuTextBoxBackup
+ ld a, SCRIPT_FINISHED
+ ld [wFieldMoveScriptID], a
+ scf
+ ld a, SCRIPT_FAIL
+ ret
+
+Text_CantUseFlyHere: ; 03:5246
+ text "ここでは つかえません!"
+ prompt
+
+FlyScript: ; 03:5254
+ ld a, MAPSETUP_TELEPORT
+ ldh [hMapEntryMethod], a
+ jpab Functionfcc24
+
+
+
+; Sets wFieldMoveSucceeded to $f if successful, $0 if not
+DigFunction: ; 03:5260
+ call .reset
+.loop
+ ld a, [wFieldMoveScriptID]
+ bit SCRIPT_FINISHED_F, a
+ jr nz, .finish
+ ld hl, DigTable
+ call CallJumptable
+ jr .loop
+
+; Finish by returning only the low nibble
+.finish
+ and $FF - SCRIPT_FINISHED_MASK
+ ld [wFieldMoveSucceeded], a
+ ret
+
+.reset
+ xor a
+ ld [wFieldMoveScriptID], a
+ ret
+
+DigTable: ; 03:527D
+ dw CheckCanDig
+ dw DoDig
+ dw FailDig
+
+CheckCanDig: ; 03:5283
+ call GetMapEnvironment
+ cp INDOOR
+ jr z, .success
+ cp CAVE
+ jr z, .success
+ ld a, SCRIPT_ID_02
+ ld [wFieldMoveScriptID], a
+ ret
+.success
+ ld a, SCRIPT_ID_01
+ ld [wFieldMoveScriptID], a
+ ret
+
+DoDig: ; 03:529a
+ ld hl, DigScript
+ ldh a, [hROMBank]
+ call QueueScript
+ ld a, SCRIPT_FINISHED_MASK | SCRIPT_SUCCESS
+ ld [wFieldMoveScriptID], a
+ ret
+
+FailDig: ; 03:52a8
+ ld hl, Text_CantUseDigHere
+ call MenuTextBoxBackup
+ ld a, SCRIPT_FINISHED_MASK | SCRIPT_FAIL
+ ld [wFieldMoveScriptID], a
+ ret
+
+Text_CantUseDigHere: ; 03:52b4
+ text "ここでは つかえません!"
+ prompt
+
+DigScript: ; 03:52c2
+ ld hl, wDigWarpNumber
+ ld de, wNextWarp
+ ld bc, 3
+ call CopyBytes
+ ld a, MAPSETUP_WARP
+ ldh [hMapEntryMethod], a
+ jpab Functionfcc24
+
+EmptyFunctiond2da: ; 03:52da
+ ret
+
+
+
+; Sets wFieldMoveSucceeded to $f if successful, $0 if not
TeleportFunction: ; 03:52db
xor a
ld [wFieldMoveScriptID], a
.loop
ld a, [wFieldMoveScriptID]
- bit SCRIPT_FINISHED, a
+ bit SCRIPT_FINISHED_F, a
jr nz, .finish
- ld hl, .JumpTable
+ ld hl, TeleportTable
call CallJumptable
jr .loop
@@ -20,13 +482,13 @@ TeleportFunction: ; 03:52db
ld [wFieldMoveSucceeded], a
ret
-.JumpTable
- dw .TryTeleport
- dw .DoTeleport
- dw .FailTeleport
- dw .CheckIfSpawnPoint
+TeleportTable
+ dw TryTeleport
+ dw DoTeleport
+ dw FailTeleport
+ dw CheckIfSpawnPoint
-.TryTeleport: ; 03:52fc
+TryTeleport: ; 03:52fc
call GetMapEnvironment
cp TOWN
jr z, .success
@@ -40,54 +502,54 @@ TeleportFunction: ; 03:52db
ld [wFieldMoveScriptID], a
ret
-.CheckIfSpawnPoint ; 03:5313
+CheckIfSpawnPoint ; 03:5313
ld a, [wLastSpawnMapGroup]
ld d, a
ld a, [wLastSpawnMapNumber]
ld e, a
callab IsSpawnPoint
jr c, .not_spawn
- ld hl, .Text_CantFindDestination
+ ld hl, Text_CantFindDestination
call MenuTextBoxBackup
- ld a, SCRIPT_FAIL
+ ld a, SCRIPT_FINISHED_MASK | SCRIPT_FAIL
ld [wFieldMoveScriptID], a
ret
.not_spawn
ld a, c
- ld [wDefaultSpawnpoint], a
+ ld [wDefaultSpawnPoint], a
ld a, SCRIPT_ID_01
ld [wFieldMoveScriptID], a
ret
-.Text_CantFindDestination: ; 03:533B
+Text_CantFindDestination: ; 03:533B
text "とびさきが みつかりません"
para
done
-.DoTeleport: ; 03:534b
+DoTeleport: ; 03:534b
ldh a, [hROMBank]
- ld hl, .TeleportScript
+ ld hl, TeleportScript
call QueueScript
- ld a, SCRIPT_SUCCESS
+ ld a, SCRIPT_FINISHED_MASK | SCRIPT_SUCCESS
ld [wFieldMoveScriptID], a
ret
-.FailTeleport: ; 03:5359
- ld hl, .Text_CantUseHere
+FailTeleport: ; 03:5359
+ ld hl, Text_CantUseTeleportHere
call MenuTextBoxBackup
- ld a, SCRIPT_FAIL
+ ld a, SCRIPT_FINISHED_MASK | SCRIPT_FAIL
ld [wFieldMoveScriptID], a
scf
ret
-.Text_CantUseHere: ; 03:5366
+Text_CantUseTeleportHere: ; 03:5366
text "ここでは つかえません!"
para
done
-.TeleportScript: ; 03:5375
+TeleportScript: ; 03:5375
call RefreshScreen
- ld hl, .Text_ReturnToLastMonCenter
+ ld hl, Text_ReturnToLastMonCenter
call MenuTextBox
ld c, 60
call DelayFrames
@@ -97,7 +559,7 @@ TeleportFunction: ; 03:52db
ldh [hMapEntryMethod], a
jpab Functionfcc24
-.Text_ReturnToLastMonCenter: ; 03:5395
+Text_ReturnToLastMonCenter: ; 03:5395
text "さいごに たちよった"
line "#センターにもどります"
done \ No newline at end of file
diff --git a/engine/items/inventory.asm b/engine/items/inventory.asm
index 9c5a1ec..9524d70 100755
--- a/engine/items/inventory.asm
+++ b/engine/items/inventory.asm
@@ -1,6 +1,6 @@
INCLUDE "constants.asm"
-SECTION "AddItemToInventory_", ROMX[$4AA1], BANK[$03]
+SECTION "Inventory", ROMX[$4AA1], BANK[$03]
_ReceiveItem: ; 03:4AA1
call DoesHLEqualwNumBagItems
@@ -587,6 +587,52 @@ GetNumberedTMHM: ; 03:4D1A
.not_machine
and a
ret
+
+SECTION "GetItemAmount", ROMX[$4e10], BANK[$03]
+
+; Returns carry if user has the item
+; and the amount in b
+GetItemAmount: ; 03:4e10
+ call CheckAmountInItemPocket
+ ret c
+ call CheckAmountInKeyItems
+ ret c
+ ld b, 0
+ and a
+ ret
+
+; Returns the amount of item b in b
+CheckAmountInItemPocket: ; 03:4E1C
+ ld hl, wItems
+.loop
+ inc hl
+ ld a, [hli]
+ cp -1
+ ret z
+ cp b
+ jr nz, .loop
+
+ ld a, [hl]
+ ld b, a
+ scf
+ ret
+
+; Returns the amount of item b in b
+CheckAmountInKeyItems: ; 03:4E2B
+ ld hl, wNumKeyItems
+ ld a, [hli]
+ and a
+ ret z
+
+.loop
+ ld a, [hli]
+ cp -1
+ ret z
+ cp b
+ jr nz, .loop
+ ld b, 1
+ scf
+ ret
SECTION "_CheckTossableItem", ROMX[$53AD], BANK[$03]
diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm
new file mode 100755
index 0000000..4ee9f42
--- /dev/null
+++ b/engine/items/item_effects.asm
@@ -0,0 +1,79 @@
+INCLUDE "constants.asm"
+
+SECTION "ApplyPPUp", ROMX[$78f6], BANK[$03]
+
+ApplyPPUp: ; 03:78f6
+ ld a, MON_MOVES
+ call GetPartyParamLocation
+ push hl
+ ld de, wStringBuffer1
+ predef FillPP
+ pop hl
+ ld c, MON_PP - MON_MOVES
+ ld b, 0
+ add hl, bc
+ ld de, wStringBuffer1 + 1
+ ld b, 0
+.loop
+ inc b
+ ld a, b
+ cp NUM_MOVES + 1
+ ret z
+ ld a, [wce37]
+ dec a
+ jr nz, .use
+ ld a, [wMenuCursorY]
+ inc a
+ cp b
+ jr nz, .skip
+.use
+ ld a, [hl]
+ and PP_UP_MASK
+ call nz, ComputeMaxPP
+.skip
+ inc hl
+ inc de
+ jr .loop
+
+ComputeMaxPP: ; 03:792B
+ push bc
+ ; Divide the base PP by 5.
+ ld a, [de]
+ ldh [hDividend + 3], a
+ xor a
+ ldh [hDividend], a
+ ldh [hDividend + 1], a
+ ldh [hDividend + 2], a
+ ld a, 5
+ ldh [hDivisor], a
+ ld b, 4
+ call Divide
+ ; Get the number of PP, which are bits 6 and 7 of the PP value stored in RAM.
+ ld a, [hl]
+ ld b, a
+ swap a
+ and $f
+ srl a
+ srl a
+ ld c, a
+.loop
+ ; Normally, a move with 40 PP would have 64 PP with three PP Ups.
+ ; Since this would overflow into bit 6, we prevent that from happening
+ ; by decreasing the extra amount of PP each PP Up provides, resulting
+ ; in a maximum of 61.
+ ldh a, [hQuotient + 2]
+ cp $8
+ jr c, .okay
+ ld a, $7
+.okay
+ add b
+ ld b, a
+ ld a, [wce37]
+ dec a
+ jr z, .no_pp_up
+ dec c
+ jr nz, .loop
+.no_pp_up
+ ld [hl], b
+ pop bc
+ ret \ No newline at end of file
diff --git a/engine/overworld/spawn_points.asm b/engine/overworld/spawn_points.asm
index 81b04b0..ca654fd 100755
--- a/engine/overworld/spawn_points.asm
+++ b/engine/overworld/spawn_points.asm
@@ -3,10 +3,10 @@ INCLUDE "constants.asm"
SECTION "LoadSpawnPoint", ROMX[$4791], BANK[$03]
LoadSpawnPoint: ; 03:4791
-; loads the spawn point in wDefaultSpawnpoint
+; loads the spawn point in wDefaultSpawnPoint
push hl
push de
- ld a, [wDefaultSpawnpoint]
+ ld a, [wDefaultSpawnPoint]
and a
jr z, .skip
dec a
diff --git a/engine/pokemon/health.asm b/engine/pokemon/health.asm
new file mode 100755
index 0000000..2810fd5
--- /dev/null
+++ b/engine/pokemon/health.asm
@@ -0,0 +1,359 @@
+INCLUDE "constants.asm"
+
+SECTION "HealParty", ROMX[$4d6f], BANK[$03]
+
+HealParty: ; 03:4d6f
+ ld hl, wPartySpecies
+ ld de, wPartyMons
+
+.party_loop
+ ld a, [hli]
+ cp -1
+ jr z, .party_done
+ push hl
+ push de
+
+; Clear the status
+ ld hl, MON_STATUS
+ add hl, de
+ xor a
+ ld [hli], a
+ ld [hl], a
+
+; Reset the PP
+ ld hl, MON_MOVES
+ add hl, de
+ ld b, NUM_MOVES
+
+.move_loop
+ push hl
+ push bc
+ ld a, [hl]
+ and a
+ jr z, .next_move
+ dec a
+ push hl
+ ld hl, Moves
+ ld bc, MOVE_DATA_SIZE
+ call AddNTimes
+ ld a, BANK(Moves)
+ call GetFarByte
+ pop hl
+ ld bc, MON_PP - MON_MOVES
+ add hl, bc
+ ld b, a
+ ld a, [hl]
+ and PP_UP_MASK
+ add b
+ ld [hl], a
+
+.next_move
+ pop bc
+ pop hl
+ inc hl
+ dec b
+ jr nz, .move_loop
+
+; Reset the HP
+ pop de
+ push de
+ ld hl, MON_MAXHP
+ add hl, de
+ ld b, h
+ ld c, l
+ dec bc
+ dec bc
+ ld a, [hli]
+ ld [bc], a
+ inc bc
+ ld a, [hl]
+ ld [bc], a
+ pop de
+ pop hl
+ push hl
+ ld hl, PARTYMON_STRUCT_LENGTH
+ add hl, de
+ ld d, h
+ ld e, l
+ pop hl
+ jr .party_loop
+
+.party_done
+ xor a
+ ld [wWhichPokemon], a
+ ld [wce37], a
+ ld a, [wPartyCount]
+ ld b, a
+
+.pp_up
+ push bc
+ call ApplyPPUp
+ pop bc
+ ld hl, wWhichPokemon
+ inc [hl]
+ dec b
+ jr nz, .pp_up
+ ret
+
+SECTION "HP Bar", ROMX[$4e3c], BANK[$03]
+
+ComputeHPBarPixels: ; 03:4e3c
+ push hl
+ xor a
+ ldh [hMultiplicand], a
+ ld a, b
+ ldh [hMultiplicand + 1], a
+ ld a, c
+ ldh [hMultiplicand + 2], a
+ ld a, HP_BAR_LENGTH_PX
+ ldh [hMultiplier], a
+ call Multiply
+ ; We need de to be under 256 because hDivisor is only 1 byte.
+ ld a, d
+ and a
+ jr z, .divide
+ ; divide de and hProduct by 4
+ srl d
+ rr e
+ srl d
+ rr e
+ ldh a, [hProduct + 2]
+ ld b, a
+ ldh a, [hProduct + 3]
+ srl b
+ rr a
+ srl b
+ rr a
+ ldh [hDividend + 3], a
+ ld a, b
+ ldh [hDividend + 2], a
+.divide
+ ld a, e
+ ldh [hDivisor], a
+ ld b, 4
+ call Divide
+ ldh a, [hQuotient + 2]
+ ld e, a
+ pop hl
+ and a
+ ret nz
+ ld e, 1
+ ret
+
+UpdateHPBar: ; 03:4e7c
+ ld a, [wHPBarOldHP]
+ ld c, a
+ ld a, [wHPBarOldHP + 1]
+ ld b, a
+ ld a, [wHPBarNewHP]
+ ld e, a
+ ld a, [wHPBarNewHP + 1]
+ ld d, a
+ push de
+ push bc
+ call UpdateHPBar_CalcHPDifference
+ ld a, e
+ ld [wHPBarHPDifference + 1], a
+ ld a, d
+ ld [wHPBarHPDifference], a
+ pop bc
+ pop de
+ call UpdateHPBar_CompareNewHPToOldHP
+ ret z
+ ld a, -1
+ jr c, .hp_decrease
+ ld a, 1
+.hp_decrease
+ ld [wHPBarDelta], a
+ ld a, [wHPBarNewHP]
+ ld e, a
+ ld a, [wHPBarNewHP + 1]
+ ld d, a
+.animate_hp_bar_loop
+ push de
+ ld a, [wHPBarOldHP]
+ ld c, a
+ ld a, [wHPBarOldHP + 1]
+ ld b, a
+ call UpdateHPBar_CompareNewHPToOldHP
+ jr z, .animate_hp_bar_done
+ jr nc, .hp_increase
+
+;hp_decrease
+ dec bc
+ ld a, c
+ ld [wHPBarNewHP], a
+ ld a, b
+ ld [wHPBarNewHP + 1], a
+ call UpdateHPBar_CalcOldNewHPBarPixels
+ ld a, e
+ sub d
+ jr .apply
+.hp_increase
+ inc bc
+ ld a, c
+ ld [wHPBarNewHP], a
+ ld a, b
+ ld [wHPBarNewHP + 1], a
+ call UpdateHPBar_CalcOldNewHPBarPixels
+ ld a, d
+ sub e
+.apply
+ call UpdateHPBar_PrintHPNumber
+ and a
+ jr z, .no_pixel_difference
+ call UpdateHPBar_AnimateHPBar
+.no_pixel_difference
+ ld a, [wHPBarNewHP]
+ ld [wHPBarOldHP], a
+ ld a, [wHPBarNewHP + 1]
+ ld [wHPBarOldHP + 1], a
+ pop de
+ jr .animate_hp_bar_loop
+.animate_hp_bar_done
+ pop de
+ ld a, e
+ ld [wHPBarOldHP], a
+ ld a, d
+ ld [wHPBarOldHP + 1], a
+ or e
+ jr z, .mon_fainted
+ call UpdateHPBar_CalcOldNewHPBarPixels
+ ld d, e
+.mon_fainted
+ call UpdateHPBar_PrintHPNumber
+ ld a, 1
+ call UpdateHPBar_AnimateHPBar
+ jp WaitBGMap
+
+; animates the HP bar going up or down for (a) ticks (two waiting frames each)
+; stops prematurely if bar is filled up
+; e: current health (in pixels) to start with
+UpdateHPBar_AnimateHPBar: ; 03:4F11
+ push hl
+
+.bar_animation_loop
+ push af
+ push de
+ ld d, HP_BAR_LENGTH
+ ld a, [wHPBarType]
+ and BATTLE_HP_BAR
+ ld b, a
+ call DrawBattleHPBar
+ ld c, 2
+ call DelayFrames
+ pop de
+ ld a, [wHPBarDelta]
+ add e
+ cp HP_BAR_LENGTH_PX + 1
+ jr nc, .bar_filled_up
+ ld e, a
+ pop af
+ dec a
+ jr nz, .bar_animation_loop
+ pop hl
+ ret
+.bar_filled_up
+ pop af
+ pop hl
+ ret
+
+; compares old HP and new HP and sets c and z flags accordingly
+UpdateHPBar_CompareNewHPToOldHP: ; 03:4F37
+ ld a, d
+ sub b
+ ret nz
+ ld a, e
+ sub c
+ ret
+
+; calcs HP difference between bc and de (into de)
+UpdateHPBar_CalcHPDifference: ; 03:4F3D
+ ld a, d
+ sub b
+ jr c, .old_hp_greater
+ jr z, .test_lower_byte
+.new_hp_greater
+ ld a, e
+ sub c
+ ld e, a
+ ld a, d
+ sbc b
+ ld d, a
+ ret
+.old_hp_greater
+ ld a, c
+ sub e
+ ld e, a
+ ld a, b
+ sbc d
+ ld d, a
+ ret
+.test_lower_byte
+ ld a, e
+ sub c
+ jr c, .old_hp_greater
+ jr nz, .new_hp_greater
+ ld de, 0
+ ret
+
+UpdateHPBar_PrintHPNumber: ; 03:4F5B
+ push af
+ push de
+ ld a, [wHPBarType]
+ and a
+ jr z, .done
+ ld a, [wHPBarOldHP]
+ ld [wHPBarTempHP + 1], a
+ ld a, [wHPBarOldHP + 1]
+ ld [wHPBarTempHP], a
+ push hl
+ ld de, SCREEN_WIDTH + 1
+ add hl, de
+ push hl
+ ld a, " "
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ pop hl
+ ld de, wHPBarTempHP
+ lb bc, 2, 3
+ call PrintNumber
+ call DelayFrame
+ pop hl
+.done
+ pop de
+ pop af
+ ret
+
+; calcs number of HP bar pixels for old and new HP value
+; d: new pixels
+; e: old pixels
+UpdateHPBar_CalcOldNewHPBarPixels: ; 03:4F8B
+ push hl
+ ld hl, wHPBarMaxHP
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ ld a, [hli]
+ ld c, a
+ ld a, [hli]
+ ld b, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ push hl
+ push de
+ call ComputeHPBarPixels
+ ld a, e
+ pop de
+ pop bc
+ push af
+ call ComputeHPBarPixels
+ pop af
+ ld d, e
+ ld e, a
+ pop hl
+ ret
+