shithub: pokered

Download patch

ref: 10211cc461b35140c815e18e95f7070eb0dcc586
parent: 2fe782b11a039b52fd236da28fb2f1ae10cae7db
author: xCrystal <rgr.crystal@gmail.com>
date: Wed Apr 1 13:03:05 EDT 2015

Rename battle files and split move effects Part 5

15.asm, 16.asm, 1a.asm, 1c.asm

--- a/engine/battle/15.asm
+++ /dev/null
@@ -1,372 +1,0 @@
-GainExperience: ; 5524f (15:524f)
-	ld a, [wLinkState]
-	cp LINK_STATE_BATTLING
-	ret z ; return if link battle
-	call DivideExpDataByNumMonsGainingExp
-	ld hl, wPartyMon1
-	xor a
-	ld [wWhichPokemon], a
-.partyMonLoop ; loop over each mon and add gained exp
-	inc hl
-	ld a, [hli]
-	or [hl] ; is mon's HP 0?
-	jp z, .nextMon ; if so, go to next mon
-	push hl
-	ld hl, wPartyGainExpFlags
-	ld a, [wWhichPokemon]
-	ld c, a
-	ld b, $2
-	predef FlagActionPredef
-	ld a, c
-	and a ; is mon's gain exp flag set?
-	pop hl
-	jp z, .nextMon ; if mon's gain exp flag not set, go to next mon
-	ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1)
-	add hl, de
-	ld d, h
-	ld e, l
-	ld hl, wEnemyMonBaseStats
-	ld c, $5
-.gainStatExpLoop
-	ld a, [hli]
-	ld b, a ; enemy mon base stat
-	ld a, [de] ; stat exp
-	add b ; add enemy mon base state to stat exp
-	ld [de], a
-	jr nc, .nextBaseStat
-; if there was a carry, increment the upper byte
-	dec de
-	ld a, [de]
-	inc a
-	jr z, .maxStatExp ; jump if the value overflowed
-	ld [de], a
-	inc de
-	jr .nextBaseStat
-.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp
-	ld a, $ff
-	ld [de], a
-	inc de
-	ld [de], a
-.nextBaseStat
-	dec c
-	jr z, .asm_552a1
-	inc de
-	inc de
-	jr .gainStatExpLoop
-.asm_552a1
-	xor a
-	ld [H_MULTIPLICAND], a
-	ld [H_MULTIPLICAND + 1], a
-	ld a, [wEnemyMonBaseExp]
-	ld [H_MULTIPLICAND + 2], a
-	ld a, [wEnemyMonLevel]
-	ld [H_MULTIPLIER], a
-	call Multiply
-	ld a, 7
-	ld [H_DIVISOR], a
-	ld b, 4
-	call Divide
-	ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2)
-	add hl, de
-	ld b, [hl] ; party mon OTID
-	inc hl
-	ld a, [wPlayerID]
-	cp b
-	jr nz, .tradedMon
-	ld b, [hl]
-	ld a, [wPlayerID + 1]
-	cp b
-	ld a, $0
-	jr z, .next
-.tradedMon
-	call BoostExp ; traded mon exp boost
-	ld a, $1
-.next
-	ld [wGainBoostedExp], a
-	ld a, [W_ISINBATTLE]
-	dec a ; is it a trainer battle?
-	call nz, BoostExp ; if so, boost exp
-	inc hl
-	inc hl
-	inc hl
-; add the gained exp to the party mon's exp
-	ld b, [hl]
-	ld a, [H_QUOTIENT + 3]
-	ld [wcf4c], a
-	add b
-	ld [hld], a
-	ld b, [hl]
-	ld a, [H_QUOTIENT + 2]
-	ld [wcf4b], a
-	adc b
-	ld [hl], a
-	jr nc, .noCarry
-	dec hl
-	inc [hl]
-	inc hl
-.noCarry
-; calculate exp for the mon at max level, and cap the exp at that value
-	inc hl
-	push hl
-	ld a, [wWhichPokemon]
-	ld c, a
-	ld b, 0
-	ld hl, wPartySpecies
-	add hl, bc
-	ld a, [hl] ; species
-	ld [wd0b5], a
-	call GetMonHeader
-	ld d, MAX_LEVEL
-	callab CalcExperience ; get max exp
-; compare max exp with current exp
-	ld a, [$ff96]
-	ld b, a
-	ld a, [$ff97]
-	ld c, a
-	ld a, [$ff98]
-	ld d, a
-	pop hl
-	ld a, [hld]
-	sub d
-	ld a, [hld]
-	sbc c
-	ld a, [hl]
-	sbc b
-	jr c, .next2
-; the mon's exp is greater than the max exp, so overwrite it with the max exp
-	ld a, b
-	ld [hli], a
-	ld a, c
-	ld [hli], a
-	ld a, d
-	ld [hld], a
-	dec hl
-.next2
-	push hl
-	ld a, [wWhichPokemon]
-	ld hl, wPartyMonNicks
-	call GetPartyMonName
-	ld hl, GainedText
-	call PrintText
-	xor a ; party mon data
-	ld [wcc49], a
-	call LoadMonData
-	pop hl
-	ld bc, wPartyMon1Level - wPartyMon1Exp
-	add hl, bc
-	push hl
-	callba CalcLevelFromExperience
-	pop hl
-	ld a, [hl] ; current level
-	cp d
-	jp z, .nextMon ; if level didn't change, go to next mon
-	ld a, [W_CURENEMYLVL]
-	push af
-	push hl
-	ld a, d
-	ld [W_CURENEMYLVL], a
-	ld [hl], a
-	ld bc, wPartyMon1Species - wPartyMon1Level
-	add hl, bc
-	ld a, [hl] ; species
-	ld [wd0b5], a
-	ld [wd11e], a
-	call GetMonHeader
-	ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species
-	add hl, bc
-	push hl
-	ld a, [hld]
-	ld c, a
-	ld b, [hl]
-	push bc ; push max HP (from before levelling up)
-	ld d, h
-	ld e, l
-	ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP
-	add hl, bc
-	ld b, $1 ; consider stat exp when calculating stats
-	call CalcStats
-	pop bc ; pop max HP (from before levelling up)
-	pop hl
-	ld a, [hld]
-	sub c
-	ld c, a
-	ld a, [hl]
-	sbc b
-	ld b, a ; bc = difference between old max HP and new max HP after levelling
-	ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP
-	add hl, de
-; add to the current HP the amount of max HP gained when levelling
-	ld a, [hl] ; wPartyMon1HP + 1
-	add c
-	ld [hld], a
-	ld a, [hl] ; wPartyMon1HP + 1
-	adc b
-	ld [hl], a ; wPartyMon1HP
-	ld a, [wPlayerMonNumber]
-	ld b, a
-	ld a, [wWhichPokemon]
-	cp b ; is the current mon in battle?
-	jr nz, .printGrewLevelText
-; current mon is in battle
-	ld de, wBattleMonHP
-; copy party mon HP to battle mon HP
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-; copy other stats from party mon to battle mon
-	ld bc, wPartyMon1Level - (wPartyMon1HP + 1)
-	add hl, bc
-	push hl
-	ld de, wBattleMonLevel
-	ld bc, $b ; size of stats
-	call CopyData
-	pop hl
-	ld a, [W_PLAYERBATTSTATUS3]
-	bit 3, a ; is the mon transformed?
-	jr nz, .recalcStatChanges
-; the mon is not transformed, so update the unmodified stats
-	ld de, wPlayerMonUnmodifiedLevel
-	ld bc, $b
-	call CopyData
-.recalcStatChanges
-	xor a
-	ld [wd11e], a
-	callab CalculateModifiedStats
-	callab ApplyBurnAndParalysisPenaltiesToPlayer
-	callab ApplyBadgeStatBoosts
-	callab DrawPlayerHUDAndHPBar
-	callab PrintEmptyString
-	call SaveScreenTilesToBuffer1
-.printGrewLevelText
-	ld hl, GrewLevelText
-	call PrintText
-	xor a ; party mon data
-	ld [wcc49], a
-	call LoadMonData
-	ld d, $1
-	callab PrintStatsBox
-	call WaitForTextScrollButtonPress
-	call LoadScreenTilesFromBuffer1
-	xor a
-	ld [wcc49], a
-	ld a, [wd0b5]
-	ld [wd11e], a
-	predef LearnMoveFromLevelUp
-	ld hl, wccd3
-	ld a, [wWhichPokemon]
-	ld c, a
-	ld b, $1
-	predef FlagActionPredef
-	pop hl
-	pop af
-	ld [W_CURENEMYLVL], a
-
-.nextMon
-	ld a, [wPartyCount]
-	ld b, a
-	ld a, [wWhichPokemon]
-	inc a
-	cp b
-	jr z, .done
-	ld [wWhichPokemon], a
-	ld bc, wPartyMon2 - wPartyMon1
-	ld hl, wPartyMon1
-	call AddNTimes
-	jp .partyMonLoop
-.done
-	ld hl, wPartyGainExpFlags
-	xor a
-	ld [hl], a ; clear gain exp flags
-	ld a, [wPlayerMonNumber]
-	ld c, a
-	ld b, $1
-	push bc
-	predef FlagActionPredef ; set the gain exp flag for the mon that is currently out
-	ld hl, wPartyFoughtCurrentEnemyFlags
-	xor a
-	ld [hl], a
-	pop bc
-	predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out
-
-; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp
-DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c)
-	ld a, [wPartyGainExpFlags]
-	ld b, a
-	xor a
-	ld c, $8
-	ld d, $0
-.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags
-	xor a
-	srl b
-	adc d
-	ld d, a
-	dec c
-	jr nz, .countSetBitsLoop
-	cp $2
-	ret c ; return if only one mon is gaining exp
-	ld [wd11e], a ; store number of mons gaining exp
-	ld hl, wEnemyMonBaseStats
-	ld c, $7
-.divideLoop
-	xor a
-	ld [H_DIVIDEND], a
-	ld a, [hl]
-	ld [H_DIVIDEND + 1], a
-	ld a, [wd11e]
-	ld [H_DIVISOR], a
-	ld b, $2
-	call Divide ; divide value by number of mons gaining exp
-	ld a, [H_QUOTIENT + 3]
-	ld [hli], a
-	dec c
-	jr nz, .divideLoop
-	ret
-
-; multiplies exp by 1.5
-BoostExp: ; 5549f (15:549f)
-	ld a, [H_QUOTIENT + 2]
-	ld b, a
-	ld a, [H_QUOTIENT + 3]
-	ld c, a
-	srl b
-	rr c
-	add c
-	ld [H_QUOTIENT + 3], a
-	ld a, [H_QUOTIENT + 2]
-	adc b
-	ld [H_QUOTIENT + 2], a
-	ret
-
-GainedText: ; 554b2 (15:54b2)
-	TX_FAR _GainedText
-	db $08 ; asm
-	ld a, [wBoostExpByExpAll]
-	ld hl, WithExpAllText
-	and a
-	ret nz
-	ld hl, ExpPointsText
-	ld a, [wGainBoostedExp]
-	and a
-	ret z
-	ld hl, BoostedText
-	ret
-
-WithExpAllText: ; 554cb (15:54cb)
-	TX_FAR _WithExpAllText
-	db $08 ; asm
-	ld hl, ExpPointsText
-	ret
-
-BoostedText: ; 554d4 (15:54d4)
-	TX_FAR _BoostedText
-
-ExpPointsText: ; 554d8 (15:54d8)
-	TX_FAR _ExpPointsText
-	db "@"
-
-GrewLevelText: ; 554dd (15:54dd)
-	TX_FAR _GrewLevelText
-	db $0b
-	db "@"
--- a/engine/battle/16.asm
+++ /dev/null
@@ -1,238 +1,0 @@
-PrintBeginningBattleText: ; 58d99 (16:4d99)
-	ld a, [W_ISINBATTLE] ; W_ISINBATTLE
-	dec a
-	jr nz, .trainerBattle
-	ld a, [W_CURMAP] ; W_CURMAP
-	cp POKEMONTOWER_3
-	jr c, .notPokemonTower
-	cp LAVENDER_HOUSE_1
-	jr c, .pokemonTower
-.notPokemonTower
-	ld a, [wEnemyMonSpecies2]
-	call PlayCry
-	ld hl, WildMonAppearedText
-	ld a, [W_MOVEMISSED] ; W_MOVEMISSED
-	and a
-	jr z, .notFishing
-	ld hl, HookedMonAttackedText
-.notFishing
-	jr .wildBattle
-.trainerBattle
-	call .playSFX
-	ld c, $14
-	call DelayFrames
-	ld hl, TrainerWantsToFightText
-.wildBattle
-	push hl
-	callab DrawAllPokeballs
-	pop hl
-	call PrintText
-	jr .done
-.pokemonTower
-	ld b, SILPH_SCOPE
-	call IsItemInBag
-	ld a, [wEnemyMonSpecies2]
-	ld [wcf91], a
-	cp MAROWAK
-	jr z, .isMarowak
-	ld a, b
-	and a
-	jr z, .noSilphScope
-	callab LoadEnemyMonData
-	jr .notPokemonTower
-.noSilphScope
-	ld hl, EnemyAppearedText
-	call PrintText
-	ld hl, GhostCantBeIDdText
-	call PrintText
-	jr .done
-.isMarowak
-	ld a, b
-	and a
-	jr z, .noSilphScope
-	ld hl, EnemyAppearedText
-	call PrintText
-	ld hl, UnveiledGhostText
-	call PrintText
-	callab LoadEnemyMonData
-	callab MarowakAnim
-	ld hl, WildMonAppearedText
-	call PrintText
-
-.playSFX
-	xor a
-	ld [wc0f1], a
-	ld a, $80
-	ld [wc0f2], a
-	ld a, (SFX_08_77 - SFX_Headers_08) / 3
-	call PlaySound
-	jp WaitForSoundToFinish
-.done
-	ret
-
-WildMonAppearedText: ; 58e3b (16:4e3b)
-	TX_FAR _WildMonAppearedText
-	db "@"
-
-HookedMonAttackedText: ; 58e40 (16:4e40)
-	TX_FAR _HookedMonAttackedText
-	db "@"
-
-EnemyAppearedText: ; 58e45 (16:4e45)
-	TX_FAR _EnemyAppearedText
-	db "@"
-
-TrainerWantsToFightText: ; 58e4a (16:4e4a)
-	TX_FAR _TrainerWantsToFightText
-	db "@"
-
-UnveiledGhostText: ; 58e4f (16:4e4f)
-	TX_FAR _UnveiledGhostText
-	db "@"
-
-GhostCantBeIDdText: ; 58e54 (16:4e54)
-	TX_FAR _GhostCantBeIDdText
-	db "@"
-
-PrintSendOutMonMessage: ; 58e59 (16:4e59)
-	ld hl, wEnemyMonHP
-	ld a, [hli]
-	or [hl]
-	ld hl, GoText
-	jr z, .printText
-	xor a
-	ld [H_MULTIPLICAND], a
-	ld hl, wEnemyMonHP
-	ld a, [hli]
-	ld [wcce3], a
-	ld [H_MULTIPLICAND + 1], a
-	ld a, [hl]
-	ld [wcce4], a
-	ld [H_MULTIPLICAND + 2], a
-	ld a, 25
-	ld [H_MULTIPLIER], a
-	call Multiply
-	ld hl, wEnemyMonMaxHP
-	ld a, [hli]
-	ld b, [hl]
-	srl a
-	rr b
-	srl a
-	rr b
-	ld a, b
-	ld b, $4
-	ld [H_DIVISOR], a ; enemy mon max HP divided by 4
-	call Divide
-	ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP
-	ld hl, GoText ; 70% or greater
-	cp 70
-	jr nc, .printText
-	ld hl, DoItText ; 40% - 69%
-	cp 40
-	jr nc, .printText
-	ld hl, GetmText ; 10% - 39%
-	cp 10
-	jr nc, .printText
-	ld hl, EnemysWeakText ; 0% - 9%
-.printText
-	jp PrintText
-
-GoText: ; 58eae (16:4eae)
-	TX_FAR _GoText
-	db $08 ; asm
-	jr PrintPlayerMon1Text
-
-DoItText: ; 58eb5 (16:4eb5)
-	TX_FAR _DoItText
-	db $08 ; asm
-	jr PrintPlayerMon1Text
-
-GetmText: ; 58ebc (16:4ebc)
-	TX_FAR _GetmText
-	db $08 ; asm
-	jr PrintPlayerMon1Text
-
-EnemysWeakText: ; 58ec3 (16:4ec3)
-	TX_FAR _EnemysWeakText
-	db $08 ; asm
-
-PrintPlayerMon1Text:
-	ld hl, PlayerMon1Text
-	ret
-
-PlayerMon1Text: ; 58ecc (16:4ecc)
-	TX_FAR _PlayerMon1Text
-	db "@"
-
-RetreatMon: ; 58ed1 (16:4ed1)
-	ld hl, PlayerMon2Text
-	jp PrintText
-
-PlayerMon2Text: ; 58ed7 (16:4ed7)
-	TX_FAR _PlayerMon2Text
-	db $08 ; asm
-	push de
-	push bc
-	ld hl, wEnemyMonHP + 1
-	ld de, wcce4
-	ld b, [hl]
-	dec hl
-	ld a, [de]
-	sub b
-	ld [$ff98], a
-	dec de
-	ld b, [hl]
-	ld a, [de]
-	sbc b
-	ld [$ff97], a
-	ld a, $19
-	ld [H_POWEROFTEN], a
-	call Multiply
-	ld hl, wEnemyMonMaxHP
-	ld a, [hli]
-	ld b, [hl]
-	srl a
-	rr b
-	srl a
-	rr b
-	ld a, b
-	ld b, $4
-	ld [H_POWEROFTEN], a
-	call Divide
-	pop bc
-	pop de
-	ld a, [$ff98]
-	ld hl, EnoughText
-	and a
-	ret z
-	ld hl, ComeBackText
-	cp $1e
-	ret c
-	ld hl, OKExclamationText
-	cp $46
-	ret c
-	ld hl, GoodText
-	ret
-
-EnoughText: ; 58f25 (16:4f25)
-	TX_FAR _EnoughText
-	db $08 ; asm
-	jr PrintComeBackText
-
-OKExclamationText: ; 58f2c (16:4f2c)
-	TX_FAR _OKExclamationText
-	db $08 ; asm
-	jr PrintComeBackText
-
-GoodText: ; 58f33 (16:4f33)
-	TX_FAR _GoodText
-	db $08 ; asm
-	jr PrintComeBackText
-
-PrintComeBackText: ; 58f3a (16:4f3a)
-	ld hl, ComeBackText
-	ret
-
-ComeBackText: ; 58f3e (16:4f3e)
-	TX_FAR _ComeBackText
-	db "@"
--- a/engine/battle/1a.asm
+++ /dev/null
@@ -1,43 +1,0 @@
-DecrementPP: ; 68000 (1a:4000)
-; after using a move, decrement pp in battle and (if not transformed?) in party
-	ld a, [de]
-	cp a, STRUGGLE
-	ret z                ; if the pokemon is using "struggle", there's nothing to do
-	                     ; we don't decrement PP for "struggle"
-	ld hl, W_PLAYERBATTSTATUS1
-	ld a, [hli]          ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the
-	                     ; W_PLAYERBATTSTATUS2 status flags later
-	and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes)
-	ret nz               ; if any of these statuses are true, don't decrement PP
-	bit UsingRage, [hl]         
-	ret nz               ; don't decrement PP either if Pokemon is using Rage
-	ld hl, wBattleMonPP  ; PP of first move (in battle)
-	
-; decrement PP in the battle struct	
-	call .DecrementPP    
-	
-; decrement PP in the party struct	
-	ld a, [W_PLAYERBATTSTATUS3]        
-	bit Transformed, a
-	ret nz               ; Return if transformed. Pokemon Red stores the "current pokemon's" PP
-	                     ; separately from the "Pokemon in your party's" PP.  This is
-	                     ; duplication -- in all cases *other* than Pokemon with Transform.
-	                     ; Normally, this means we have to go on and make the same
-	                     ; modification to the "party's pokemon" PP that we made to the
-	                     ; "current pokemon's" PP.  But, if we're dealing with a Transformed
-	                     ; Pokemon, it has separate PP for the move set that it copied from
-	                     ; its opponent, which is *not* the same as its real PP as part of your
-	                     ; party.  So we return, and don't do that part.
-
-	ld hl, wPartyMon1PP  ; PP of first move (in party)
-	ld a, [wPlayerMonNumber] ; which mon in party is active
-	ld bc, wPartyMon2 - wPartyMon1 
-	call AddNTimes       ; calculate address of the mon to modify
-.DecrementPP
-	ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use?
-	ld c, a
-	ld b, 0
-	add hl ,bc           ; calculate the address in memory of the PP we need to decrement
-	                     ; based on the move chosen.
-	dec [hl]             ; Decrement PP
-	ret
--- a/engine/battle/1c.asm
+++ /dev/null
@@ -1,905 +1,0 @@
-MarowakAnim: ; 708ca (1c:48ca)
-; animate the ghost being unveiled as a Marowak
-	ld a, $e4
-	ld [rOBP1], a
-	call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same
-; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap
-	hlCoord 12, 0
-	ld bc, $707
-	call ClearScreenArea
-	call Delay3
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon
-; replace ghost pic with Marowak in BG
-	ld a, MAROWAK
-	ld [wHPBarMaxHP], a
-	ld a, $1
-	ld [H_WHOSETURN], a
-	callab Func_79793
- ; alternate between black and light grey 8 times.
- ; this makes the ghost's body appear to flash
-	ld d, $80
-	call FlashSprite8Times
-.fadeOutGhostLoop
-	ld c, 10
-	call DelayFrames
-	ld a, [rOBP1]
-	sla a
-	sla a
-	ld [rOBP1], a
-	jr nz, .fadeOutGhostLoop
-	call ClearSprites
-	call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM
-	ld b, $e4
-.fadeInMarowakLoop
-	ld c, 10
-	call DelayFrames
-	ld a, [rOBP1]
-	srl b
-	rra
-	srl b
-	rra
-	ld [rOBP1], a
-	ld a, b
-	and a
-	jr nz, .fadeInMarowakLoop
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared
-	call Delay3
-	jp ClearSprites
-
-; copies a mon pic's  from background VRAM to sprite VRAM and sets up OAM
-CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a)
-	ld de, vFrontPic
-	ld hl, vSprites
-	ld bc, 7 * 7
-	call CopyVideoData
-	ld a, $10
-	ld [W_BASECOORDY], a
-	ld a, $70
-	ld [W_BASECOORDX], a
-	ld hl, wOAMBuffer
-	ld bc, $606
-	ld d, $8
-.oamLoop
-	push bc
-	ld a, [W_BASECOORDY]
-	ld e, a
-.oamInnerLoop
-	ld a, e
-	add $8
-	ld e, a
-	ld [hli], a
-	ld a, [W_BASECOORDX]
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-	ld a, $10 ; use OBP1
-	ld [hli], a
-	inc d
-	dec c
-	jr nz, .oamInnerLoop
-	inc d
-	ld a, [W_BASECOORDX]
-	add $8
-	ld [W_BASECOORDX], a
-	pop bc
-	dec b
-	jr nz, .oamLoop
-	ret
-
-BattleTransition: ; 7096d (1c:496d)
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a
-	call Delay3
-	xor a
-	ld [hWY], a
-	dec a
-	ld [wUpdateSpritesEnabled], a
-	call DelayFrame
-	ld hl, wSpriteStateData1 + 2
-	ld a, [H_DOWNARROWBLINKCNT2]
-	ld c, a
-	ld b, $0
-	ld de, $10
-.loop1
-	ld a, [hl]
-	cp $ff
-	jr z, .skip1
-	inc b
-.skip1
-	add hl, de
-	dec c
-	jr nz, .loop1
-	ld hl, wOAMBuffer + $10
-	ld c, $9
-.loop2
-	ld a, b
-	swap a
-	cp l
-	jr z, .skip2
-	push hl
-	push bc
-	ld bc, $10
-	xor a
-	call FillMemory
-	pop bc
-	pop hl
-.skip2
-	ld de, $10
-	add hl, de
-	dec c
-	jr nz, .loop2
-	call Delay3
-	call LoadBattleTransitionTile
-	ld bc, $0
-	ld a, [wLinkState]
-	cp LINK_STATE_BATTLING
-	jr z, .linkBattle
-	call GetBattleTransitionID_WildOrTrainer
-	call GetBattleTransitionID_CompareLevels
-	call GetBattleTransitionID_IsDungeonMap
-.linkBattle
-	ld hl, BattleTransitions
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp [hl]
-
-; the three GetBattleTransitionID functions set the first
-; three bits of c, which determines what transition animation
-; to play at the beginning of a battle
-; bit 0: set if trainer battle
-; bit 1: set if enemy is at least 3 levels higher than player
-; bit 2: set if dungeon map
-BattleTransitions: ; 709d2 (1c:49d2)
-	dw BattleTransition_DoubleCircle      ; %000
-	dw BattleTransition_Spiral            ; %001
-	dw BattleTransition_Circle            ; %010
-	dw BattleTransition_Spiral            ; %011
-	dw BattleTransition_HorizontalStripes ; %100
-	dw BattleTransition_Shrink            ; %101
-	dw BattleTransition_VerticalStripes   ; %110
-	dw BattleTransition_Split             ; %111
-
-GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2)
-	ld a, [W_CUROPPONENT]
-	cp $c8
-	jr nc, .trainer
-	res 0, c
-	ret
-.trainer
-	set 0, c
-	ret
-
-GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef)
-	ld hl, wPartyMon1HP
-.faintedLoop
-	ld a, [hli]
-	or [hl]
-	jr nz, .notFainted
-	ld de, wPartyMon2 - (wPartyMon1 + 1)
-	add hl, de
-	jr .faintedLoop
-.notFainted
-	ld de, wPartyMon1Level - (wPartyMon1HP + 1)
-	add hl, de
-	ld a, [hl]
-	add $3
-	ld e, a
-	ld a, [W_CURENEMYLVL]
-	sub e
-	jr nc, .highLevelEnemy
-	res 1, c
-	ld a, $1
-	ld [wcd47], a
-	ret
-.highLevelEnemy
-	set 1, c
-	xor a
-	ld [wcd47], a
-	ret
-
-; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps,
-; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE
-; and SILPH_CO_[9-11]F as dungeon maps
-GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19)
-	ld a, [W_CURMAP]
-	ld e, a
-	ld hl, DungeonMaps1
-.loop1
-	ld a, [hli]
-	cp $ff
-	jr z, .noMatch1
-	cp e
-	jr nz, .loop1
-.match
-	set 2, c
-	ret
-.noMatch1
-	ld hl, DungeonMaps2
-.loop2
-	ld a, [hli]
-	cp $ff
-	jr z, .noMatch2
-	ld d, a
-	ld a, [hli]
-	cp e
-	jr c, .loop2
-	ld a, e
-	cp d
-	jr nc, .match
-.noMatch2
-	res 2, c
-	ret
-
-; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
-; is equal to one of these maps
-DungeonMaps1: ; 70a3f (1c:4a3f)
-	db VIRIDIAN_FOREST
-	db ROCK_TUNNEL_1
-	db SEAFOAM_ISLANDS_1
-	db ROCK_TUNNEL_2
-	db $FF
-
-; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
-; is in between or equal to each pair of maps
-DungeonMaps2: ; 70a44 (1c:4a44)
-	; all MT_MOON maps
-	db MT_MOON_1
-	db MT_MOON_3
-
-	; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME
-	db SS_ANNE_1
-	db HALL_OF_FAME
-
-	; all POKEMONTOWER maps and Lavender Town buildings
-	db LAVENDER_POKECENTER
-	db LAVENDER_HOUSE_2
-
-	; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps,
-	; except for SILPH_CO_1F
-	db SILPH_CO_2F
-	db UNKNOWN_DUNGEON_1
-	db $FF
-
-LoadBattleTransitionTile: ; 70a4d (1c:4a4d)
-	ld hl, vChars1 + $7f0
-	ld de, BattleTransitionTile
-	ld bc, (BANK(BattleTransitionTile) << 8) + $01
-	jp CopyVideoData
-
-BattleTransitionTile: ; 70a59 (1c:4a59)
-	INCBIN "gfx/battle_transition.2bpp"
-
-BattleTransition_BlackScreen: ; 70a69 (1c:4a69)
-	ld a, $ff
-	ld [rBGP], a
-	ld [rOBP0], a
-	ld [rOBP1], a
-	ret
-
-; for non-dungeon trainer battles
-; called regardless of mon levels, but does an
-; outward spiral if enemy is at least 3 levels
-; higher than player and does an inward spiral otherwise
-BattleTransition_Spiral: ; 70a72 (1c:4a72)
-	ld a, [wcd47]
-	and a
-	jr z, .outwardSpiral
-	call BattleTransition_InwardSpiral
-	jr .done
-.outwardSpiral
-	hlCoord 10, 10
-	ld a, $3
-	ld [wd09f], a
-	ld a, l
-	ld [wd09b], a
-	ld a, h
-	ld [wd09a], a
-	ld b, $78
-.loop1
-	ld c, $3
-.loop2
-	push bc
-	call BattleTransition_OutwardSpiral_
-	pop bc
-	dec c
-	jr nz, .loop2
-	call DelayFrame
-	dec b
-	jr nz, .loop1
-.done
-	call BattleTransition_BlackScreen
-	xor a
-	ld [wd09b], a
-	ld [wd09a], a
-	ret
-
-BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa)
-	ld a, $7
-	ld [wWhichTrade], a
-	ld hl, wTileMap
-	ld c, $11
-	ld de, $14
-	call BattleTransition_InwardSpiral_
-	inc c
-	jr .skip
-.loop
-	ld de, $14
-	call BattleTransition_InwardSpiral_
-.skip
-	inc c
-	ld de, $1
-	call BattleTransition_InwardSpiral_
-	dec c
-	dec c
-	ld de, $ffec
-	call BattleTransition_InwardSpiral_
-	inc c
-	ld de, rIE
-	call BattleTransition_InwardSpiral_
-	dec c
-	dec c
-	ld a, c
-	and a
-	jr nz, .loop
-	ret
-
-BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0)
-	push bc
-.loop
-	ld [hl], $ff
-	add hl, de
-	push bc
-	ld a, [wWhichTrade]
-	dec a
-	jr nz, .skip
-	call BattleTransition_TransferDelay3
-	ld a, $7
-.skip
-	ld [wWhichTrade], a
-	pop bc
-	dec c
-	jr nz, .loop
-	pop bc
-	ret
-
-BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9)
-	ld bc, $ffec
-	ld de, $14
-	ld a, [wd09b]
-	ld l, a
-	ld a, [wd09a]
-	ld h, a
-	ld a, [wd09f]
-	cp $0
-	jr z, .zero
-	cp $1
-	jr z, .one
-	cp $2
-	jr z, .two
-	cp $3
-	jr z, .three
-.done1
-	ld [hl], $ff
-.done2_
-	ld a, l
-	ld [wd09b], a
-	ld a, h
-	ld [wd09a], a
-	ret
-.zero
-	dec hl
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	inc hl
-	add hl, bc
-	jr .done1
-.one
-	add hl, de
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	add hl, bc
-	dec hl
-	jr .done1
-.two
-	inc hl
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	dec hl
-	add hl, de
-	jr .done1
-.three
-	add hl, bc
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	add hl, de
-	inc hl
-	jr .done1
-.done2
-	ld [hl], $ff
-	ld a, [wd09f]
-	inc a
-	cp $4
-	jr nz, .skip
-	xor a
-.skip
-	ld [wd09f], a
-	jr .done2_
-
-FlashScreen:
-BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d)
-	ld hl, BattleTransition_FlashScreenPalettes
-.loop
-	ld a, [hli]
-	cp $1
-	jr z, .done
-	ld [rBGP], a
-	ld c, $2
-	call DelayFrames
-	jr .loop
-.done
-	dec b
-	jr nz, BattleTransition_FlashScreen_
-	ret
-
-BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72)
-	db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4
-	db $01 ; terminator
-
-; used for low level trainer dungeon battles
-BattleTransition_Shrink: ; 70b7f (1c:4b7f)
-	ld c, $9
-.loop
-	push bc
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-	hlCoord 0, 7
-	deCoord 0, 8
-	ld bc, $ffd8
-	call BattleTransition_CopyTiles1
-	hlCoord 0, 10
-	deCoord 0, 9
-	ld bc, $28
-	call BattleTransition_CopyTiles1
-	hlCoord 8, 0
-	deCoord 9, 0
-	ld bc, $fffe
-	call BattleTransition_CopyTiles2
-	hlCoord 11, 0
-	deCoord 10, 0
-	ld bc, $2
-	call BattleTransition_CopyTiles2
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a
-	ld c, $6
-	call DelayFrames
-	pop bc
-	dec c
-	jr nz, .loop
-	call BattleTransition_BlackScreen
-	ld c, $a
-	jp DelayFrames
-
-; used for high level trainer dungeon battles
-BattleTransition_Split: ; 70bca (1c:4bca)
-	ld c, $9
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-.loop
-	push bc
-	hlCoord 0, 16
-	deCoord 0, 17
-	ld bc, $ffd8
-	call BattleTransition_CopyTiles1
-	hlCoord 0, 1
-	ld de, wTileMap
-	ld bc, $28
-	call BattleTransition_CopyTiles1
-	hlCoord 18, 0
-	deCoord 19, 0
-	ld bc, $fffe
-	call BattleTransition_CopyTiles2
-	hlCoord 1, 0
-	ld de, wTileMap
-	ld bc, $2
-	call BattleTransition_CopyTiles2
-	call BattleTransition_TransferDelay3
-	call Delay3
-	pop bc
-	dec c
-	jr nz, .loop
-	call BattleTransition_BlackScreen
-	ld c, $a
-	jp DelayFrames
-
-BattleTransition_CopyTiles1: ; 70c12 (1c:4c12)
-	ld a, c
-	ld [wWhichTrade], a
-	ld a, b
-	ld [wTrainerEngageDistance], a
-	ld c, $8
-.loop1
-	push bc
-	push hl
-	push de
-	ld bc, $14
-	call CopyData
-	pop hl
-	pop de
-	ld a, [wWhichTrade]
-	ld c, a
-	ld a, [wTrainerEngageDistance]
-	ld b, a
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop1
-	ld l, e
-	ld h, d
-	ld a, $ff
-	ld c, $14
-.loop2
-	ld [hli], a
-	dec c
-	jr nz, .loop2
-	ret
-
-BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f)
-	ld a, c
-	ld [wWhichTrade], a
-	ld a, b
-	ld [wTrainerEngageDistance], a
-	ld c, $9
-.loop1
-	push bc
-	push hl
-	push de
-	ld c, $12
-.loop2
-	ld a, [hl]
-	ld [de], a
-	ld a, e
-	add $14
-	jr nc, .noCarry1
-	inc d
-.noCarry1
-	ld e, a
-	ld a, l
-	add $14
-	jr nc, .noCarry2
-	inc h
-.noCarry2
-	ld l, a
-	dec c
-	jr nz, .loop2
-	pop hl
-	pop de
-	ld a, [wWhichTrade]
-	ld c, a
-	ld a, [wTrainerEngageDistance]
-	ld b, a
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop1
-	ld l, e
-	ld h, d
-	ld de, $14
-	ld c, $12
-.loop3
-	ld [hl], $ff
-	add hl, de
-	dec c
-	jr nz, .loop3
-	ret
-
-; used for high level wild dungeon battles
-BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e)
-	ld c, $12
-	ld hl, wTileMap
-	deCoord 1, 17
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-.loop
-	push bc
-	push hl
-	push de
-	push de
-	call BattleTransition_VerticalStripes_
-	pop hl
-	call BattleTransition_VerticalStripes_
-	call BattleTransition_TransferDelay3
-	pop hl
-	ld bc, $ffec
-	add hl, bc
-	ld e, l
-	ld d, h
-	pop hl
-	ld bc, $14
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop
-	jp BattleTransition_BlackScreen
-
-BattleTransition_VerticalStripes_: ; 70caa (1c:4caa)
-	ld c, $a
-.loop
-	ld [hl], $ff
-	inc hl
-	inc hl
-	dec c
-	jr nz, .loop
-	ret
-
-; used for low level wild dungeon battles
-BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4)
-	ld c, $14
-	ld hl, wTileMap
-	deCoord 19, 1
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-.loop
-	push bc
-	push hl
-	push de
-	push de
-	call BattleTransition_HorizontalStripes_
-	pop hl
-	call BattleTransition_HorizontalStripes_
-	call BattleTransition_TransferDelay3
-	pop de
-	pop hl
-	pop bc
-	inc hl
-	dec de
-	dec c
-	jr nz, .loop
-	jp BattleTransition_BlackScreen
-
-BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8)
-	ld c, $9
-	ld de, $28
-.loop
-	ld [hl], $ff
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-
-; used for high level wild non-dungeon battles
-; makes one full circle around the screen
-; by animating each half circle one at a time
-BattleTransition_Circle: ; 70ce4 (1c:4ce4)
-	call BattleTransition_FlashScreen
-	ld bc, $000a
-	ld hl, BattleTransition_HalfCircle1
-	call BattleTransition_Circle_Sub1
-	ld c, $a
-	ld b, $1
-	ld hl, BattleTransition_HalfCircle2
-	call BattleTransition_Circle_Sub1
-	jp BattleTransition_BlackScreen
-
-BattleTransition_FlashScreen: ; 70cfd (1c:4cfd)
-	ld b, $3
-	call BattleTransition_FlashScreen_
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-	ret
-
-BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06)
-	push bc
-	push hl
-	ld a, b
-	call BattleTransition_Circle_Sub2
-	pop hl
-	ld bc, $0005
-	add hl, bc
-	call BattleTransition_TransferDelay3
-	pop bc
-	dec c
-	jr nz, BattleTransition_Circle_Sub1
-	ret
-
-BattleTransition_TransferDelay3: ; 70d19 (1c:4d19)
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a
-	call Delay3
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-	ret
-
-; used for low level wild non-dungeon battles
-; makes two half circles around the screen
-; by animating both half circles at the same time
-BattleTransition_DoubleCircle: ; 70d24 (1c:4d24)
-	call BattleTransition_FlashScreen
-	ld c, $a
-	ld hl, BattleTransition_HalfCircle1
-	ld de, BattleTransition_HalfCircle2
-.loop
-	push bc
-	push hl
-	push de
-	push de
-	xor a
-	call BattleTransition_Circle_Sub2
-	pop hl
-	ld a, $1
-	call BattleTransition_Circle_Sub2
-	pop hl
-	ld bc, $5
-	add hl, bc
-	ld e, l
-	ld d, h
-	pop hl
-	add hl, bc
-	call BattleTransition_TransferDelay3
-	pop bc
-	dec c
-	jr nz, .loop
-	jp BattleTransition_BlackScreen
-
-BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50)
-	ld [wWhichTrade], a
-	ld a, [hli]
-	ld [wTrainerEngageDistance], a
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp BattleTransition_Circle_Sub3
-
-BattleTransition_HalfCircle1: ; 70d61 (1c:4d61)
-	db $01
-	dw BattleTransition_CircleData1
-	dwCoord 18, 6
-
-	db $01
-	dw BattleTransition_CircleData2
-	dwCoord 19, 3
-
-	db $01
-	dw BattleTransition_CircleData3
-	dwCoord 18, 0
-
-	db $01
-	dw BattleTransition_CircleData4
-	dwCoord 14, 0
-
-	db $01
-	dw BattleTransition_CircleData5
-	dwCoord 10, 0
-
-	db $00
-	dw BattleTransition_CircleData5
-	dwCoord 9, 0
-
-	db $00
-	dw BattleTransition_CircleData4
-	dwCoord 5, 0
-
-	db $00
-	dw BattleTransition_CircleData3
-	dwCoord 1, 0
-
-	db $00
-	dw BattleTransition_CircleData2
-	dwCoord 0, 3
-
-	db $00
-	dw BattleTransition_CircleData1
-	dwCoord 1, 6
-
-BattleTransition_HalfCircle2: ; 70d93 (1c:4d93)
-	db $00
-	dw BattleTransition_CircleData1
-	dwCoord 1, 11
-
-	db $00
-	dw BattleTransition_CircleData2
-	dwCoord 0, 14
-
-	db $00
-	dw BattleTransition_CircleData3
-	dwCoord 1, 17
-
-	db $00
-	dw BattleTransition_CircleData4
-	dwCoord 5, 17
-
-	db $00
-	dw BattleTransition_CircleData5
-	dwCoord 9, 17
-
-	db $01
-	dw BattleTransition_CircleData5
-	dwCoord 10, 17
-
-	db $01
-	dw BattleTransition_CircleData4
-	dwCoord 14, 17
-
-	db $01
-	dw BattleTransition_CircleData3
-	dwCoord 18, 17
-
-	db $01
-	dw BattleTransition_CircleData2
-	dwCoord 19, 14
-
-	db $01
-	dw BattleTransition_CircleData1
-	dwCoord 18, 11
-
-BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5)
-	push hl
-	ld a, [de]
-	ld c, a
-	inc de
-.loop1
-	ld [hl], $ff
-	ld a, [wTrainerEngageDistance]
-	and a
-	jr z, .skip1
-	inc hl
-	jr .skip2
-.skip1
-	dec hl
-.skip2
-	dec c
-	jr nz, .loop1
-	pop hl
-	ld a, [wWhichTrade]
-	and a
-	ld bc, $14
-	jr z, .skip3
-	ld bc, $ffec
-.skip3
-	add hl, bc
-	ld a, [de]
-	inc de
-	cp $ff
-	ret z
-	and a
-	jr z, BattleTransition_Circle_Sub3
-	ld c, a
-.loop2
-	ld a, [wTrainerEngageDistance]
-	and a
-	jr z, .skip4
-	dec hl
-	jr .skip5
-.skip4
-	inc hl
-.skip5
-	dec c
-	jr nz, .loop2
-	jr BattleTransition_Circle_Sub3
-
-BattleTransition_CircleData1: ; 70dfe (1c:4dfe)
-	db $02,$03,$05,$04,$09,$FF
-
-BattleTransition_CircleData2: ; 70e04 (1c:4e04)
-	db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF
-
-BattleTransition_CircleData3: ; 70e0e (1c:4e0e)
-	db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF
-
-BattleTransition_CircleData4: ; 70e20 (1c:4e20)
-	db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF
-
-BattleTransition_CircleData5: ; 70e2e (1c:4e2e)
-	db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF
--- /dev/null
+++ b/engine/battle/battle_transitions.asm
@@ -1,0 +1,815 @@
+BattleTransition: ; 7096d (1c:496d)
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a
+	call Delay3
+	xor a
+	ld [hWY], a
+	dec a
+	ld [wUpdateSpritesEnabled], a
+	call DelayFrame
+	ld hl, wSpriteStateData1 + 2
+	ld a, [H_DOWNARROWBLINKCNT2]
+	ld c, a
+	ld b, $0
+	ld de, $10
+.loop1
+	ld a, [hl]
+	cp $ff
+	jr z, .skip1
+	inc b
+.skip1
+	add hl, de
+	dec c
+	jr nz, .loop1
+	ld hl, wOAMBuffer + $10
+	ld c, $9
+.loop2
+	ld a, b
+	swap a
+	cp l
+	jr z, .skip2
+	push hl
+	push bc
+	ld bc, $10
+	xor a
+	call FillMemory
+	pop bc
+	pop hl
+.skip2
+	ld de, $10
+	add hl, de
+	dec c
+	jr nz, .loop2
+	call Delay3
+	call LoadBattleTransitionTile
+	ld bc, $0
+	ld a, [wLinkState]
+	cp LINK_STATE_BATTLING
+	jr z, .linkBattle
+	call GetBattleTransitionID_WildOrTrainer
+	call GetBattleTransitionID_CompareLevels
+	call GetBattleTransitionID_IsDungeonMap
+.linkBattle
+	ld hl, BattleTransitions
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp [hl]
+
+; the three GetBattleTransitionID functions set the first
+; three bits of c, which determines what transition animation
+; to play at the beginning of a battle
+; bit 0: set if trainer battle
+; bit 1: set if enemy is at least 3 levels higher than player
+; bit 2: set if dungeon map
+BattleTransitions: ; 709d2 (1c:49d2)
+	dw BattleTransition_DoubleCircle      ; %000
+	dw BattleTransition_Spiral            ; %001
+	dw BattleTransition_Circle            ; %010
+	dw BattleTransition_Spiral            ; %011
+	dw BattleTransition_HorizontalStripes ; %100
+	dw BattleTransition_Shrink            ; %101
+	dw BattleTransition_VerticalStripes   ; %110
+	dw BattleTransition_Split             ; %111
+
+GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2)
+	ld a, [W_CUROPPONENT]
+	cp $c8
+	jr nc, .trainer
+	res 0, c
+	ret
+.trainer
+	set 0, c
+	ret
+
+GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef)
+	ld hl, wPartyMon1HP
+.faintedLoop
+	ld a, [hli]
+	or [hl]
+	jr nz, .notFainted
+	ld de, wPartyMon2 - (wPartyMon1 + 1)
+	add hl, de
+	jr .faintedLoop
+.notFainted
+	ld de, wPartyMon1Level - (wPartyMon1HP + 1)
+	add hl, de
+	ld a, [hl]
+	add $3
+	ld e, a
+	ld a, [W_CURENEMYLVL]
+	sub e
+	jr nc, .highLevelEnemy
+	res 1, c
+	ld a, $1
+	ld [wcd47], a
+	ret
+.highLevelEnemy
+	set 1, c
+	xor a
+	ld [wcd47], a
+	ret
+
+; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps,
+; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE
+; and SILPH_CO_[9-11]F as dungeon maps
+GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19)
+	ld a, [W_CURMAP]
+	ld e, a
+	ld hl, DungeonMaps1
+.loop1
+	ld a, [hli]
+	cp $ff
+	jr z, .noMatch1
+	cp e
+	jr nz, .loop1
+.match
+	set 2, c
+	ret
+.noMatch1
+	ld hl, DungeonMaps2
+.loop2
+	ld a, [hli]
+	cp $ff
+	jr z, .noMatch2
+	ld d, a
+	ld a, [hli]
+	cp e
+	jr c, .loop2
+	ld a, e
+	cp d
+	jr nc, .match
+.noMatch2
+	res 2, c
+	ret
+
+; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
+; is equal to one of these maps
+DungeonMaps1: ; 70a3f (1c:4a3f)
+	db VIRIDIAN_FOREST
+	db ROCK_TUNNEL_1
+	db SEAFOAM_ISLANDS_1
+	db ROCK_TUNNEL_2
+	db $FF
+
+; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
+; is in between or equal to each pair of maps
+DungeonMaps2: ; 70a44 (1c:4a44)
+	; all MT_MOON maps
+	db MT_MOON_1
+	db MT_MOON_3
+
+	; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME
+	db SS_ANNE_1
+	db HALL_OF_FAME
+
+	; all POKEMONTOWER maps and Lavender Town buildings
+	db LAVENDER_POKECENTER
+	db LAVENDER_HOUSE_2
+
+	; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps,
+	; except for SILPH_CO_1F
+	db SILPH_CO_2F
+	db UNKNOWN_DUNGEON_1
+	db $FF
+
+LoadBattleTransitionTile: ; 70a4d (1c:4a4d)
+	ld hl, vChars1 + $7f0
+	ld de, BattleTransitionTile
+	ld bc, (BANK(BattleTransitionTile) << 8) + $01
+	jp CopyVideoData
+
+BattleTransitionTile: ; 70a59 (1c:4a59)
+	INCBIN "gfx/battle_transition.2bpp"
+
+BattleTransition_BlackScreen: ; 70a69 (1c:4a69)
+	ld a, $ff
+	ld [rBGP], a
+	ld [rOBP0], a
+	ld [rOBP1], a
+	ret
+
+; for non-dungeon trainer battles
+; called regardless of mon levels, but does an
+; outward spiral if enemy is at least 3 levels
+; higher than player and does an inward spiral otherwise
+BattleTransition_Spiral: ; 70a72 (1c:4a72)
+	ld a, [wcd47]
+	and a
+	jr z, .outwardSpiral
+	call BattleTransition_InwardSpiral
+	jr .done
+.outwardSpiral
+	hlCoord 10, 10
+	ld a, $3
+	ld [wd09f], a
+	ld a, l
+	ld [wd09b], a
+	ld a, h
+	ld [wd09a], a
+	ld b, $78
+.loop1
+	ld c, $3
+.loop2
+	push bc
+	call BattleTransition_OutwardSpiral_
+	pop bc
+	dec c
+	jr nz, .loop2
+	call DelayFrame
+	dec b
+	jr nz, .loop1
+.done
+	call BattleTransition_BlackScreen
+	xor a
+	ld [wd09b], a
+	ld [wd09a], a
+	ret
+
+BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa)
+	ld a, $7
+	ld [wWhichTrade], a
+	ld hl, wTileMap
+	ld c, $11
+	ld de, $14
+	call BattleTransition_InwardSpiral_
+	inc c
+	jr .skip
+.loop
+	ld de, $14
+	call BattleTransition_InwardSpiral_
+.skip
+	inc c
+	ld de, $1
+	call BattleTransition_InwardSpiral_
+	dec c
+	dec c
+	ld de, $ffec
+	call BattleTransition_InwardSpiral_
+	inc c
+	ld de, rIE
+	call BattleTransition_InwardSpiral_
+	dec c
+	dec c
+	ld a, c
+	and a
+	jr nz, .loop
+	ret
+
+BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0)
+	push bc
+.loop
+	ld [hl], $ff
+	add hl, de
+	push bc
+	ld a, [wWhichTrade]
+	dec a
+	jr nz, .skip
+	call BattleTransition_TransferDelay3
+	ld a, $7
+.skip
+	ld [wWhichTrade], a
+	pop bc
+	dec c
+	jr nz, .loop
+	pop bc
+	ret
+
+BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9)
+	ld bc, $ffec
+	ld de, $14
+	ld a, [wd09b]
+	ld l, a
+	ld a, [wd09a]
+	ld h, a
+	ld a, [wd09f]
+	cp $0
+	jr z, .zero
+	cp $1
+	jr z, .one
+	cp $2
+	jr z, .two
+	cp $3
+	jr z, .three
+.done1
+	ld [hl], $ff
+.done2_
+	ld a, l
+	ld [wd09b], a
+	ld a, h
+	ld [wd09a], a
+	ret
+.zero
+	dec hl
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	inc hl
+	add hl, bc
+	jr .done1
+.one
+	add hl, de
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	add hl, bc
+	dec hl
+	jr .done1
+.two
+	inc hl
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	dec hl
+	add hl, de
+	jr .done1
+.three
+	add hl, bc
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	add hl, de
+	inc hl
+	jr .done1
+.done2
+	ld [hl], $ff
+	ld a, [wd09f]
+	inc a
+	cp $4
+	jr nz, .skip
+	xor a
+.skip
+	ld [wd09f], a
+	jr .done2_
+
+FlashScreen:
+BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d)
+	ld hl, BattleTransition_FlashScreenPalettes
+.loop
+	ld a, [hli]
+	cp $1
+	jr z, .done
+	ld [rBGP], a
+	ld c, $2
+	call DelayFrames
+	jr .loop
+.done
+	dec b
+	jr nz, BattleTransition_FlashScreen_
+	ret
+
+BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72)
+	db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4
+	db $01 ; terminator
+
+; used for low level trainer dungeon battles
+BattleTransition_Shrink: ; 70b7f (1c:4b7f)
+	ld c, $9
+.loop
+	push bc
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+	hlCoord 0, 7
+	deCoord 0, 8
+	ld bc, $ffd8
+	call BattleTransition_CopyTiles1
+	hlCoord 0, 10
+	deCoord 0, 9
+	ld bc, $28
+	call BattleTransition_CopyTiles1
+	hlCoord 8, 0
+	deCoord 9, 0
+	ld bc, $fffe
+	call BattleTransition_CopyTiles2
+	hlCoord 11, 0
+	deCoord 10, 0
+	ld bc, $2
+	call BattleTransition_CopyTiles2
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a
+	ld c, $6
+	call DelayFrames
+	pop bc
+	dec c
+	jr nz, .loop
+	call BattleTransition_BlackScreen
+	ld c, $a
+	jp DelayFrames
+
+; used for high level trainer dungeon battles
+BattleTransition_Split: ; 70bca (1c:4bca)
+	ld c, $9
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+	push bc
+	hlCoord 0, 16
+	deCoord 0, 17
+	ld bc, $ffd8
+	call BattleTransition_CopyTiles1
+	hlCoord 0, 1
+	ld de, wTileMap
+	ld bc, $28
+	call BattleTransition_CopyTiles1
+	hlCoord 18, 0
+	deCoord 19, 0
+	ld bc, $fffe
+	call BattleTransition_CopyTiles2
+	hlCoord 1, 0
+	ld de, wTileMap
+	ld bc, $2
+	call BattleTransition_CopyTiles2
+	call BattleTransition_TransferDelay3
+	call Delay3
+	pop bc
+	dec c
+	jr nz, .loop
+	call BattleTransition_BlackScreen
+	ld c, $a
+	jp DelayFrames
+
+BattleTransition_CopyTiles1: ; 70c12 (1c:4c12)
+	ld a, c
+	ld [wWhichTrade], a
+	ld a, b
+	ld [wTrainerEngageDistance], a
+	ld c, $8
+.loop1
+	push bc
+	push hl
+	push de
+	ld bc, $14
+	call CopyData
+	pop hl
+	pop de
+	ld a, [wWhichTrade]
+	ld c, a
+	ld a, [wTrainerEngageDistance]
+	ld b, a
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop1
+	ld l, e
+	ld h, d
+	ld a, $ff
+	ld c, $14
+.loop2
+	ld [hli], a
+	dec c
+	jr nz, .loop2
+	ret
+
+BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f)
+	ld a, c
+	ld [wWhichTrade], a
+	ld a, b
+	ld [wTrainerEngageDistance], a
+	ld c, $9
+.loop1
+	push bc
+	push hl
+	push de
+	ld c, $12
+.loop2
+	ld a, [hl]
+	ld [de], a
+	ld a, e
+	add $14
+	jr nc, .noCarry1
+	inc d
+.noCarry1
+	ld e, a
+	ld a, l
+	add $14
+	jr nc, .noCarry2
+	inc h
+.noCarry2
+	ld l, a
+	dec c
+	jr nz, .loop2
+	pop hl
+	pop de
+	ld a, [wWhichTrade]
+	ld c, a
+	ld a, [wTrainerEngageDistance]
+	ld b, a
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop1
+	ld l, e
+	ld h, d
+	ld de, $14
+	ld c, $12
+.loop3
+	ld [hl], $ff
+	add hl, de
+	dec c
+	jr nz, .loop3
+	ret
+
+; used for high level wild dungeon battles
+BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e)
+	ld c, $12
+	ld hl, wTileMap
+	deCoord 1, 17
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+	push bc
+	push hl
+	push de
+	push de
+	call BattleTransition_VerticalStripes_
+	pop hl
+	call BattleTransition_VerticalStripes_
+	call BattleTransition_TransferDelay3
+	pop hl
+	ld bc, $ffec
+	add hl, bc
+	ld e, l
+	ld d, h
+	pop hl
+	ld bc, $14
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop
+	jp BattleTransition_BlackScreen
+
+BattleTransition_VerticalStripes_: ; 70caa (1c:4caa)
+	ld c, $a
+.loop
+	ld [hl], $ff
+	inc hl
+	inc hl
+	dec c
+	jr nz, .loop
+	ret
+
+; used for low level wild dungeon battles
+BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4)
+	ld c, $14
+	ld hl, wTileMap
+	deCoord 19, 1
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+	push bc
+	push hl
+	push de
+	push de
+	call BattleTransition_HorizontalStripes_
+	pop hl
+	call BattleTransition_HorizontalStripes_
+	call BattleTransition_TransferDelay3
+	pop de
+	pop hl
+	pop bc
+	inc hl
+	dec de
+	dec c
+	jr nz, .loop
+	jp BattleTransition_BlackScreen
+
+BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8)
+	ld c, $9
+	ld de, $28
+.loop
+	ld [hl], $ff
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
+
+; used for high level wild non-dungeon battles
+; makes one full circle around the screen
+; by animating each half circle one at a time
+BattleTransition_Circle: ; 70ce4 (1c:4ce4)
+	call BattleTransition_FlashScreen
+	ld bc, $000a
+	ld hl, BattleTransition_HalfCircle1
+	call BattleTransition_Circle_Sub1
+	ld c, $a
+	ld b, $1
+	ld hl, BattleTransition_HalfCircle2
+	call BattleTransition_Circle_Sub1
+	jp BattleTransition_BlackScreen
+
+BattleTransition_FlashScreen: ; 70cfd (1c:4cfd)
+	ld b, $3
+	call BattleTransition_FlashScreen_
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+	ret
+
+BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06)
+	push bc
+	push hl
+	ld a, b
+	call BattleTransition_Circle_Sub2
+	pop hl
+	ld bc, $0005
+	add hl, bc
+	call BattleTransition_TransferDelay3
+	pop bc
+	dec c
+	jr nz, BattleTransition_Circle_Sub1
+	ret
+
+BattleTransition_TransferDelay3: ; 70d19 (1c:4d19)
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a
+	call Delay3
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+	ret
+
+; used for low level wild non-dungeon battles
+; makes two half circles around the screen
+; by animating both half circles at the same time
+BattleTransition_DoubleCircle: ; 70d24 (1c:4d24)
+	call BattleTransition_FlashScreen
+	ld c, $a
+	ld hl, BattleTransition_HalfCircle1
+	ld de, BattleTransition_HalfCircle2
+.loop
+	push bc
+	push hl
+	push de
+	push de
+	xor a
+	call BattleTransition_Circle_Sub2
+	pop hl
+	ld a, $1
+	call BattleTransition_Circle_Sub2
+	pop hl
+	ld bc, $5
+	add hl, bc
+	ld e, l
+	ld d, h
+	pop hl
+	add hl, bc
+	call BattleTransition_TransferDelay3
+	pop bc
+	dec c
+	jr nz, .loop
+	jp BattleTransition_BlackScreen
+
+BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50)
+	ld [wWhichTrade], a
+	ld a, [hli]
+	ld [wTrainerEngageDistance], a
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp BattleTransition_Circle_Sub3
+
+BattleTransition_HalfCircle1: ; 70d61 (1c:4d61)
+	db $01
+	dw BattleTransition_CircleData1
+	dwCoord 18, 6
+
+	db $01
+	dw BattleTransition_CircleData2
+	dwCoord 19, 3
+
+	db $01
+	dw BattleTransition_CircleData3
+	dwCoord 18, 0
+
+	db $01
+	dw BattleTransition_CircleData4
+	dwCoord 14, 0
+
+	db $01
+	dw BattleTransition_CircleData5
+	dwCoord 10, 0
+
+	db $00
+	dw BattleTransition_CircleData5
+	dwCoord 9, 0
+
+	db $00
+	dw BattleTransition_CircleData4
+	dwCoord 5, 0
+
+	db $00
+	dw BattleTransition_CircleData3
+	dwCoord 1, 0
+
+	db $00
+	dw BattleTransition_CircleData2
+	dwCoord 0, 3
+
+	db $00
+	dw BattleTransition_CircleData1
+	dwCoord 1, 6
+
+BattleTransition_HalfCircle2: ; 70d93 (1c:4d93)
+	db $00
+	dw BattleTransition_CircleData1
+	dwCoord 1, 11
+
+	db $00
+	dw BattleTransition_CircleData2
+	dwCoord 0, 14
+
+	db $00
+	dw BattleTransition_CircleData3
+	dwCoord 1, 17
+
+	db $00
+	dw BattleTransition_CircleData4
+	dwCoord 5, 17
+
+	db $00
+	dw BattleTransition_CircleData5
+	dwCoord 9, 17
+
+	db $01
+	dw BattleTransition_CircleData5
+	dwCoord 10, 17
+
+	db $01
+	dw BattleTransition_CircleData4
+	dwCoord 14, 17
+
+	db $01
+	dw BattleTransition_CircleData3
+	dwCoord 18, 17
+
+	db $01
+	dw BattleTransition_CircleData2
+	dwCoord 19, 14
+
+	db $01
+	dw BattleTransition_CircleData1
+	dwCoord 18, 11
+
+BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5)
+	push hl
+	ld a, [de]
+	ld c, a
+	inc de
+.loop1
+	ld [hl], $ff
+	ld a, [wTrainerEngageDistance]
+	and a
+	jr z, .skip1
+	inc hl
+	jr .skip2
+.skip1
+	dec hl
+.skip2
+	dec c
+	jr nz, .loop1
+	pop hl
+	ld a, [wWhichTrade]
+	and a
+	ld bc, $14
+	jr z, .skip3
+	ld bc, $ffec
+.skip3
+	add hl, bc
+	ld a, [de]
+	inc de
+	cp $ff
+	ret z
+	and a
+	jr z, BattleTransition_Circle_Sub3
+	ld c, a
+.loop2
+	ld a, [wTrainerEngageDistance]
+	and a
+	jr z, .skip4
+	dec hl
+	jr .skip5
+.skip4
+	inc hl
+.skip5
+	dec c
+	jr nz, .loop2
+	jr BattleTransition_Circle_Sub3
+
+BattleTransition_CircleData1: ; 70dfe (1c:4dfe)
+	db $02,$03,$05,$04,$09,$FF
+
+BattleTransition_CircleData2: ; 70e04 (1c:4e04)
+	db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF
+
+BattleTransition_CircleData3: ; 70e0e (1c:4e0e)
+	db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF
+
+BattleTransition_CircleData4: ; 70e20 (1c:4e20)
+	db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF
+
+BattleTransition_CircleData5: ; 70e2e (1c:4e2e)
+	db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF
--- /dev/null
+++ b/engine/battle/common_text.asm
@@ -1,0 +1,238 @@
+PrintBeginningBattleText: ; 58d99 (16:4d99)
+	ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+	dec a
+	jr nz, .trainerBattle
+	ld a, [W_CURMAP] ; W_CURMAP
+	cp POKEMONTOWER_3
+	jr c, .notPokemonTower
+	cp LAVENDER_HOUSE_1
+	jr c, .pokemonTower
+.notPokemonTower
+	ld a, [wEnemyMonSpecies2]
+	call PlayCry
+	ld hl, WildMonAppearedText
+	ld a, [W_MOVEMISSED] ; W_MOVEMISSED
+	and a
+	jr z, .notFishing
+	ld hl, HookedMonAttackedText
+.notFishing
+	jr .wildBattle
+.trainerBattle
+	call .playSFX
+	ld c, $14
+	call DelayFrames
+	ld hl, TrainerWantsToFightText
+.wildBattle
+	push hl
+	callab DrawAllPokeballs
+	pop hl
+	call PrintText
+	jr .done
+.pokemonTower
+	ld b, SILPH_SCOPE
+	call IsItemInBag
+	ld a, [wEnemyMonSpecies2]
+	ld [wcf91], a
+	cp MAROWAK
+	jr z, .isMarowak
+	ld a, b
+	and a
+	jr z, .noSilphScope
+	callab LoadEnemyMonData
+	jr .notPokemonTower
+.noSilphScope
+	ld hl, EnemyAppearedText
+	call PrintText
+	ld hl, GhostCantBeIDdText
+	call PrintText
+	jr .done
+.isMarowak
+	ld a, b
+	and a
+	jr z, .noSilphScope
+	ld hl, EnemyAppearedText
+	call PrintText
+	ld hl, UnveiledGhostText
+	call PrintText
+	callab LoadEnemyMonData
+	callab MarowakAnim
+	ld hl, WildMonAppearedText
+	call PrintText
+
+.playSFX
+	xor a
+	ld [wc0f1], a
+	ld a, $80
+	ld [wc0f2], a
+	ld a, (SFX_08_77 - SFX_Headers_08) / 3
+	call PlaySound
+	jp WaitForSoundToFinish
+.done
+	ret
+
+WildMonAppearedText: ; 58e3b (16:4e3b)
+	TX_FAR _WildMonAppearedText
+	db "@"
+
+HookedMonAttackedText: ; 58e40 (16:4e40)
+	TX_FAR _HookedMonAttackedText
+	db "@"
+
+EnemyAppearedText: ; 58e45 (16:4e45)
+	TX_FAR _EnemyAppearedText
+	db "@"
+
+TrainerWantsToFightText: ; 58e4a (16:4e4a)
+	TX_FAR _TrainerWantsToFightText
+	db "@"
+
+UnveiledGhostText: ; 58e4f (16:4e4f)
+	TX_FAR _UnveiledGhostText
+	db "@"
+
+GhostCantBeIDdText: ; 58e54 (16:4e54)
+	TX_FAR _GhostCantBeIDdText
+	db "@"
+
+PrintSendOutMonMessage: ; 58e59 (16:4e59)
+	ld hl, wEnemyMonHP
+	ld a, [hli]
+	or [hl]
+	ld hl, GoText
+	jr z, .printText
+	xor a
+	ld [H_MULTIPLICAND], a
+	ld hl, wEnemyMonHP
+	ld a, [hli]
+	ld [wcce3], a
+	ld [H_MULTIPLICAND + 1], a
+	ld a, [hl]
+	ld [wcce4], a
+	ld [H_MULTIPLICAND + 2], a
+	ld a, 25
+	ld [H_MULTIPLIER], a
+	call Multiply
+	ld hl, wEnemyMonMaxHP
+	ld a, [hli]
+	ld b, [hl]
+	srl a
+	rr b
+	srl a
+	rr b
+	ld a, b
+	ld b, $4
+	ld [H_DIVISOR], a ; enemy mon max HP divided by 4
+	call Divide
+	ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP
+	ld hl, GoText ; 70% or greater
+	cp 70
+	jr nc, .printText
+	ld hl, DoItText ; 40% - 69%
+	cp 40
+	jr nc, .printText
+	ld hl, GetmText ; 10% - 39%
+	cp 10
+	jr nc, .printText
+	ld hl, EnemysWeakText ; 0% - 9%
+.printText
+	jp PrintText
+
+GoText: ; 58eae (16:4eae)
+	TX_FAR _GoText
+	db $08 ; asm
+	jr PrintPlayerMon1Text
+
+DoItText: ; 58eb5 (16:4eb5)
+	TX_FAR _DoItText
+	db $08 ; asm
+	jr PrintPlayerMon1Text
+
+GetmText: ; 58ebc (16:4ebc)
+	TX_FAR _GetmText
+	db $08 ; asm
+	jr PrintPlayerMon1Text
+
+EnemysWeakText: ; 58ec3 (16:4ec3)
+	TX_FAR _EnemysWeakText
+	db $08 ; asm
+
+PrintPlayerMon1Text:
+	ld hl, PlayerMon1Text
+	ret
+
+PlayerMon1Text: ; 58ecc (16:4ecc)
+	TX_FAR _PlayerMon1Text
+	db "@"
+
+RetreatMon: ; 58ed1 (16:4ed1)
+	ld hl, PlayerMon2Text
+	jp PrintText
+
+PlayerMon2Text: ; 58ed7 (16:4ed7)
+	TX_FAR _PlayerMon2Text
+	db $08 ; asm
+	push de
+	push bc
+	ld hl, wEnemyMonHP + 1
+	ld de, wcce4
+	ld b, [hl]
+	dec hl
+	ld a, [de]
+	sub b
+	ld [$ff98], a
+	dec de
+	ld b, [hl]
+	ld a, [de]
+	sbc b
+	ld [$ff97], a
+	ld a, $19
+	ld [H_POWEROFTEN], a
+	call Multiply
+	ld hl, wEnemyMonMaxHP
+	ld a, [hli]
+	ld b, [hl]
+	srl a
+	rr b
+	srl a
+	rr b
+	ld a, b
+	ld b, $4
+	ld [H_POWEROFTEN], a
+	call Divide
+	pop bc
+	pop de
+	ld a, [$ff98]
+	ld hl, EnoughText
+	and a
+	ret z
+	ld hl, ComeBackText
+	cp $1e
+	ret c
+	ld hl, OKExclamationText
+	cp $46
+	ret c
+	ld hl, GoodText
+	ret
+
+EnoughText: ; 58f25 (16:4f25)
+	TX_FAR _EnoughText
+	db $08 ; asm
+	jr PrintComeBackText
+
+OKExclamationText: ; 58f2c (16:4f2c)
+	TX_FAR _OKExclamationText
+	db $08 ; asm
+	jr PrintComeBackText
+
+GoodText: ; 58f33 (16:4f33)
+	TX_FAR _GoodText
+	db $08 ; asm
+	jr PrintComeBackText
+
+PrintComeBackText: ; 58f3a (16:4f3a)
+	ld hl, ComeBackText
+	ret
+
+ComeBackText: ; 58f3e (16:4f3e)
+	TX_FAR _ComeBackText
+	db "@"
--- /dev/null
+++ b/engine/battle/decrement_pp.asm
@@ -1,0 +1,43 @@
+DecrementPP: ; 68000 (1a:4000)
+; after using a move, decrement pp in battle and (if not transformed?) in party
+	ld a, [de]
+	cp a, STRUGGLE
+	ret z                ; if the pokemon is using "struggle", there's nothing to do
+	                     ; we don't decrement PP for "struggle"
+	ld hl, W_PLAYERBATTSTATUS1
+	ld a, [hli]          ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the
+	                     ; W_PLAYERBATTSTATUS2 status flags later
+	and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes)
+	ret nz               ; if any of these statuses are true, don't decrement PP
+	bit UsingRage, [hl]         
+	ret nz               ; don't decrement PP either if Pokemon is using Rage
+	ld hl, wBattleMonPP  ; PP of first move (in battle)
+	
+; decrement PP in the battle struct	
+	call .DecrementPP    
+	
+; decrement PP in the party struct	
+	ld a, [W_PLAYERBATTSTATUS3]        
+	bit Transformed, a
+	ret nz               ; Return if transformed. Pokemon Red stores the "current pokemon's" PP
+	                     ; separately from the "Pokemon in your party's" PP.  This is
+	                     ; duplication -- in all cases *other* than Pokemon with Transform.
+	                     ; Normally, this means we have to go on and make the same
+	                     ; modification to the "party's pokemon" PP that we made to the
+	                     ; "current pokemon's" PP.  But, if we're dealing with a Transformed
+	                     ; Pokemon, it has separate PP for the move set that it copied from
+	                     ; its opponent, which is *not* the same as its real PP as part of your
+	                     ; party.  So we return, and don't do that part.
+
+	ld hl, wPartyMon1PP  ; PP of first move (in party)
+	ld a, [wPlayerMonNumber] ; which mon in party is active
+	ld bc, wPartyMon2 - wPartyMon1 
+	call AddNTimes       ; calculate address of the mon to modify
+.DecrementPP
+	ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use?
+	ld c, a
+	ld b, 0
+	add hl ,bc           ; calculate the address in memory of the PP we need to decrement
+	                     ; based on the move chosen.
+	dec [hl]             ; Decrement PP
+	ret
--- /dev/null
+++ b/engine/battle/experience.asm
@@ -1,0 +1,372 @@
+GainExperience: ; 5524f (15:524f)
+	ld a, [wLinkState]
+	cp LINK_STATE_BATTLING
+	ret z ; return if link battle
+	call DivideExpDataByNumMonsGainingExp
+	ld hl, wPartyMon1
+	xor a
+	ld [wWhichPokemon], a
+.partyMonLoop ; loop over each mon and add gained exp
+	inc hl
+	ld a, [hli]
+	or [hl] ; is mon's HP 0?
+	jp z, .nextMon ; if so, go to next mon
+	push hl
+	ld hl, wPartyGainExpFlags
+	ld a, [wWhichPokemon]
+	ld c, a
+	ld b, $2
+	predef FlagActionPredef
+	ld a, c
+	and a ; is mon's gain exp flag set?
+	pop hl
+	jp z, .nextMon ; if mon's gain exp flag not set, go to next mon
+	ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1)
+	add hl, de
+	ld d, h
+	ld e, l
+	ld hl, wEnemyMonBaseStats
+	ld c, $5
+.gainStatExpLoop
+	ld a, [hli]
+	ld b, a ; enemy mon base stat
+	ld a, [de] ; stat exp
+	add b ; add enemy mon base state to stat exp
+	ld [de], a
+	jr nc, .nextBaseStat
+; if there was a carry, increment the upper byte
+	dec de
+	ld a, [de]
+	inc a
+	jr z, .maxStatExp ; jump if the value overflowed
+	ld [de], a
+	inc de
+	jr .nextBaseStat
+.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp
+	ld a, $ff
+	ld [de], a
+	inc de
+	ld [de], a
+.nextBaseStat
+	dec c
+	jr z, .asm_552a1
+	inc de
+	inc de
+	jr .gainStatExpLoop
+.asm_552a1
+	xor a
+	ld [H_MULTIPLICAND], a
+	ld [H_MULTIPLICAND + 1], a
+	ld a, [wEnemyMonBaseExp]
+	ld [H_MULTIPLICAND + 2], a
+	ld a, [wEnemyMonLevel]
+	ld [H_MULTIPLIER], a
+	call Multiply
+	ld a, 7
+	ld [H_DIVISOR], a
+	ld b, 4
+	call Divide
+	ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2)
+	add hl, de
+	ld b, [hl] ; party mon OTID
+	inc hl
+	ld a, [wPlayerID]
+	cp b
+	jr nz, .tradedMon
+	ld b, [hl]
+	ld a, [wPlayerID + 1]
+	cp b
+	ld a, $0
+	jr z, .next
+.tradedMon
+	call BoostExp ; traded mon exp boost
+	ld a, $1
+.next
+	ld [wGainBoostedExp], a
+	ld a, [W_ISINBATTLE]
+	dec a ; is it a trainer battle?
+	call nz, BoostExp ; if so, boost exp
+	inc hl
+	inc hl
+	inc hl
+; add the gained exp to the party mon's exp
+	ld b, [hl]
+	ld a, [H_QUOTIENT + 3]
+	ld [wcf4c], a
+	add b
+	ld [hld], a
+	ld b, [hl]
+	ld a, [H_QUOTIENT + 2]
+	ld [wcf4b], a
+	adc b
+	ld [hl], a
+	jr nc, .noCarry
+	dec hl
+	inc [hl]
+	inc hl
+.noCarry
+; calculate exp for the mon at max level, and cap the exp at that value
+	inc hl
+	push hl
+	ld a, [wWhichPokemon]
+	ld c, a
+	ld b, 0
+	ld hl, wPartySpecies
+	add hl, bc
+	ld a, [hl] ; species
+	ld [wd0b5], a
+	call GetMonHeader
+	ld d, MAX_LEVEL
+	callab CalcExperience ; get max exp
+; compare max exp with current exp
+	ld a, [$ff96]
+	ld b, a
+	ld a, [$ff97]
+	ld c, a
+	ld a, [$ff98]
+	ld d, a
+	pop hl
+	ld a, [hld]
+	sub d
+	ld a, [hld]
+	sbc c
+	ld a, [hl]
+	sbc b
+	jr c, .next2
+; the mon's exp is greater than the max exp, so overwrite it with the max exp
+	ld a, b
+	ld [hli], a
+	ld a, c
+	ld [hli], a
+	ld a, d
+	ld [hld], a
+	dec hl
+.next2
+	push hl
+	ld a, [wWhichPokemon]
+	ld hl, wPartyMonNicks
+	call GetPartyMonName
+	ld hl, GainedText
+	call PrintText
+	xor a ; party mon data
+	ld [wcc49], a
+	call LoadMonData
+	pop hl
+	ld bc, wPartyMon1Level - wPartyMon1Exp
+	add hl, bc
+	push hl
+	callba CalcLevelFromExperience
+	pop hl
+	ld a, [hl] ; current level
+	cp d
+	jp z, .nextMon ; if level didn't change, go to next mon
+	ld a, [W_CURENEMYLVL]
+	push af
+	push hl
+	ld a, d
+	ld [W_CURENEMYLVL], a
+	ld [hl], a
+	ld bc, wPartyMon1Species - wPartyMon1Level
+	add hl, bc
+	ld a, [hl] ; species
+	ld [wd0b5], a
+	ld [wd11e], a
+	call GetMonHeader
+	ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species
+	add hl, bc
+	push hl
+	ld a, [hld]
+	ld c, a
+	ld b, [hl]
+	push bc ; push max HP (from before levelling up)
+	ld d, h
+	ld e, l
+	ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP
+	add hl, bc
+	ld b, $1 ; consider stat exp when calculating stats
+	call CalcStats
+	pop bc ; pop max HP (from before levelling up)
+	pop hl
+	ld a, [hld]
+	sub c
+	ld c, a
+	ld a, [hl]
+	sbc b
+	ld b, a ; bc = difference between old max HP and new max HP after levelling
+	ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP
+	add hl, de
+; add to the current HP the amount of max HP gained when levelling
+	ld a, [hl] ; wPartyMon1HP + 1
+	add c
+	ld [hld], a
+	ld a, [hl] ; wPartyMon1HP + 1
+	adc b
+	ld [hl], a ; wPartyMon1HP
+	ld a, [wPlayerMonNumber]
+	ld b, a
+	ld a, [wWhichPokemon]
+	cp b ; is the current mon in battle?
+	jr nz, .printGrewLevelText
+; current mon is in battle
+	ld de, wBattleMonHP
+; copy party mon HP to battle mon HP
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+; copy other stats from party mon to battle mon
+	ld bc, wPartyMon1Level - (wPartyMon1HP + 1)
+	add hl, bc
+	push hl
+	ld de, wBattleMonLevel
+	ld bc, $b ; size of stats
+	call CopyData
+	pop hl
+	ld a, [W_PLAYERBATTSTATUS3]
+	bit 3, a ; is the mon transformed?
+	jr nz, .recalcStatChanges
+; the mon is not transformed, so update the unmodified stats
+	ld de, wPlayerMonUnmodifiedLevel
+	ld bc, $b
+	call CopyData
+.recalcStatChanges
+	xor a
+	ld [wd11e], a
+	callab CalculateModifiedStats
+	callab ApplyBurnAndParalysisPenaltiesToPlayer
+	callab ApplyBadgeStatBoosts
+	callab DrawPlayerHUDAndHPBar
+	callab PrintEmptyString
+	call SaveScreenTilesToBuffer1
+.printGrewLevelText
+	ld hl, GrewLevelText
+	call PrintText
+	xor a ; party mon data
+	ld [wcc49], a
+	call LoadMonData
+	ld d, $1
+	callab PrintStatsBox
+	call WaitForTextScrollButtonPress
+	call LoadScreenTilesFromBuffer1
+	xor a
+	ld [wcc49], a
+	ld a, [wd0b5]
+	ld [wd11e], a
+	predef LearnMoveFromLevelUp
+	ld hl, wccd3
+	ld a, [wWhichPokemon]
+	ld c, a
+	ld b, $1
+	predef FlagActionPredef
+	pop hl
+	pop af
+	ld [W_CURENEMYLVL], a
+
+.nextMon
+	ld a, [wPartyCount]
+	ld b, a
+	ld a, [wWhichPokemon]
+	inc a
+	cp b
+	jr z, .done
+	ld [wWhichPokemon], a
+	ld bc, wPartyMon2 - wPartyMon1
+	ld hl, wPartyMon1
+	call AddNTimes
+	jp .partyMonLoop
+.done
+	ld hl, wPartyGainExpFlags
+	xor a
+	ld [hl], a ; clear gain exp flags
+	ld a, [wPlayerMonNumber]
+	ld c, a
+	ld b, $1
+	push bc
+	predef FlagActionPredef ; set the gain exp flag for the mon that is currently out
+	ld hl, wPartyFoughtCurrentEnemyFlags
+	xor a
+	ld [hl], a
+	pop bc
+	predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out
+
+; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp
+DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c)
+	ld a, [wPartyGainExpFlags]
+	ld b, a
+	xor a
+	ld c, $8
+	ld d, $0
+.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags
+	xor a
+	srl b
+	adc d
+	ld d, a
+	dec c
+	jr nz, .countSetBitsLoop
+	cp $2
+	ret c ; return if only one mon is gaining exp
+	ld [wd11e], a ; store number of mons gaining exp
+	ld hl, wEnemyMonBaseStats
+	ld c, $7
+.divideLoop
+	xor a
+	ld [H_DIVIDEND], a
+	ld a, [hl]
+	ld [H_DIVIDEND + 1], a
+	ld a, [wd11e]
+	ld [H_DIVISOR], a
+	ld b, $2
+	call Divide ; divide value by number of mons gaining exp
+	ld a, [H_QUOTIENT + 3]
+	ld [hli], a
+	dec c
+	jr nz, .divideLoop
+	ret
+
+; multiplies exp by 1.5
+BoostExp: ; 5549f (15:549f)
+	ld a, [H_QUOTIENT + 2]
+	ld b, a
+	ld a, [H_QUOTIENT + 3]
+	ld c, a
+	srl b
+	rr c
+	add c
+	ld [H_QUOTIENT + 3], a
+	ld a, [H_QUOTIENT + 2]
+	adc b
+	ld [H_QUOTIENT + 2], a
+	ret
+
+GainedText: ; 554b2 (15:54b2)
+	TX_FAR _GainedText
+	db $08 ; asm
+	ld a, [wBoostExpByExpAll]
+	ld hl, WithExpAllText
+	and a
+	ret nz
+	ld hl, ExpPointsText
+	ld a, [wGainBoostedExp]
+	and a
+	ret z
+	ld hl, BoostedText
+	ret
+
+WithExpAllText: ; 554cb (15:54cb)
+	TX_FAR _WithExpAllText
+	db $08 ; asm
+	ld hl, ExpPointsText
+	ret
+
+BoostedText: ; 554d4 (15:54d4)
+	TX_FAR _BoostedText
+
+ExpPointsText: ; 554d8 (15:54d8)
+	TX_FAR _ExpPointsText
+	db "@"
+
+GrewLevelText: ; 554dd (15:54dd)
+	TX_FAR _GrewLevelText
+	db $0b
+	db "@"
--- /dev/null
+++ b/engine/battle/ghost_marowak_anim.asm
@@ -1,0 +1,89 @@
+MarowakAnim: ; 708ca (1c:48ca)
+; animate the ghost being unveiled as a Marowak
+	ld a, $e4
+	ld [rOBP1], a
+	call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same
+; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap
+	hlCoord 12, 0
+	ld bc, $707
+	call ClearScreenArea
+	call Delay3
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon
+; replace ghost pic with Marowak in BG
+	ld a, MAROWAK
+	ld [wHPBarMaxHP], a
+	ld a, $1
+	ld [H_WHOSETURN], a
+	callab Func_79793
+ ; alternate between black and light grey 8 times.
+ ; this makes the ghost's body appear to flash
+	ld d, $80
+	call FlashSprite8Times
+.fadeOutGhostLoop
+	ld c, 10
+	call DelayFrames
+	ld a, [rOBP1]
+	sla a
+	sla a
+	ld [rOBP1], a
+	jr nz, .fadeOutGhostLoop
+	call ClearSprites
+	call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM
+	ld b, $e4
+.fadeInMarowakLoop
+	ld c, 10
+	call DelayFrames
+	ld a, [rOBP1]
+	srl b
+	rra
+	srl b
+	rra
+	ld [rOBP1], a
+	ld a, b
+	and a
+	jr nz, .fadeInMarowakLoop
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared
+	call Delay3
+	jp ClearSprites
+
+; copies a mon pic's  from background VRAM to sprite VRAM and sets up OAM
+CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a)
+	ld de, vFrontPic
+	ld hl, vSprites
+	ld bc, 7 * 7
+	call CopyVideoData
+	ld a, $10
+	ld [W_BASECOORDY], a
+	ld a, $70
+	ld [W_BASECOORDX], a
+	ld hl, wOAMBuffer
+	ld bc, $606
+	ld d, $8
+.oamLoop
+	push bc
+	ld a, [W_BASECOORDY]
+	ld e, a
+.oamInnerLoop
+	ld a, e
+	add $8
+	ld e, a
+	ld [hli], a
+	ld a, [W_BASECOORDX]
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+	ld a, $10 ; use OBP1
+	ld [hli], a
+	inc d
+	dec c
+	jr nz, .oamInnerLoop
+	inc d
+	ld a, [W_BASECOORDX]
+	add $8
+	ld [W_BASECOORDX], a
+	pop bc
+	dec b
+	jr nz, .oamLoop
+	ret
--- a/main.asm
+++ b/main.asm
@@ -6014,7 +6014,7 @@
 
 FuchsiaHouse3Blocks: INCBIN "maps/fuchsiahouse3.blk"
 
-INCLUDE "engine/battle/15.asm"
+INCLUDE "engine/battle/experience.asm"
 
 INCLUDE "scripts/route2.asm"
 INCLUDE "scripts/route3.asm"
@@ -6094,7 +6094,7 @@
 
 	INCBIN "maps/unusedblocks58d7d.blk"
 
-INCLUDE "engine/battle/16.asm"
+INCLUDE "engine/battle/common_text.asm"
 
 INCLUDE "engine/experience.asm"
 
@@ -6451,7 +6451,7 @@
 
 SECTION "bank1A",ROMX,BANK[$1A]
 
-INCLUDE "engine/battle/1a.asm"
+INCLUDE "engine/battle/decrement_pp.asm"
 
 Version_GFX:
 IF DEF(_RED)
@@ -6508,7 +6508,8 @@
 INCLUDE "engine/hall_of_fame.asm"
 INCLUDE "engine/overworld/healing_machine.asm"
 INCLUDE "engine/overworld/player_animations.asm"
-INCLUDE "engine/battle/1c.asm"
+INCLUDE "engine/battle/ghost_marowak_anim.asm"
+INCLUDE "engine/battle/battle_transitions.asm"
 INCLUDE "engine/town_map.asm"
 INCLUDE "engine/mon_party_sprites.asm"
 INCLUDE "engine/in_game_trades.asm"