summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Huderle <huderlem@gmail.com>2017-06-30 16:27:25 -0700
committerMarcus Huderle <huderlem@gmail.com>2017-06-30 16:27:25 -0700
commit5bf01e71c492d9377ba72507e8cc514f46cb28e5 (patch)
tree259d2c6d39d06434252fb5411259d000e66f1827
parentbe488b67709c44227d151fdbf6e0adf323e91f0c (diff)
Move ball loss routines to engine/pinball_game/ball_loss/. Move flipper routines into flippers.asm
-rwxr-xr-xengine/pinball_game.asm343
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss.asm34
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss_blue_field.asm93
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss_diglett_bonus.asm24
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss_gengar_bonus.asm50
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss_meowth_bonus.asm57
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss_mewtwo_bonus.asm50
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss_red_field.asm104
-rwxr-xr-xengine/pinball_game/ball_loss/ball_loss_seel_bonus.asm56
-rwxr-xr-xengine/pinball_game/flippers.asm772
-rwxr-xr-xengine/pinball_game/save_game.asm21
-rwxr-xr-xengine/pinball_game/stage_init/init_stages.asm2
-rwxr-xr-xmain.asm1618
13 files changed, 1614 insertions, 1610 deletions
diff --git a/engine/pinball_game.asm b/engine/pinball_game.asm
index 8915818..ac4db27 100755
--- a/engine/pinball_game.asm
+++ b/engine/pinball_game.asm
@@ -7,3 +7,346 @@ PinballGameScreenFunctions: ; 0xd857
dw GameScreenFunction_HandleBallPhysics
dw GameScreenFunction_HandleBallLoss
dw GameScreenFunction_EndBall
+
+GameScreenFunction_LoadGFX: ; 0xd861
+ xor a
+ ld [wd908], a
+ callba InitializeCurrentStage
+ call FillBottomMessageBufferWithBlackTile
+ ld a, $1
+ ld [wd85d], a
+ ld [wd4aa], a
+ ld hl, wScreenState
+ inc [hl]
+ ret
+
+GameScreenFunction_StartBall: ; 0xd87f
+ ld a, $67
+ ld [hLCDC], a
+ ld a, $e4
+ ld [wBGP], a
+ ld a, $e1
+ ld [wOBP0], a
+ ld a, $e4
+ ld [wOBP1], a
+ ld a, [wSCX]
+ ld [hSCX], a
+ xor a
+ ld [hSCY], a
+ ld a, $7
+ ld [hWX], a
+ ld a, $83
+ ld [hLYC], a
+ ld [hLastLYC], a
+ ld a, $ff
+ ld [hLCDCMask], a
+ ld hl, hSTAT
+ set 6, [hl]
+ ld hl, rIE
+ set 1, [hl]
+ ld a, $1
+ ld [hHBlankRoutine], a
+ callba InitBallForStage
+ callba LoadStageCollisionAttributes
+ callba LoadStageData
+ callba Func_ed5e
+ call ClearOAMBuffer
+ callba DrawSpritesForStage
+ ld a, [wd849]
+ and a
+ call nz, Func_e5d
+ ld a, $1
+ ld [wd4aa], a
+ xor a
+ ld [wd7c1], a
+ call Func_b66
+ call Func_588
+ call Func_bbe
+ ld hl, wScreenState
+ inc [hl]
+ ret
+
+GameScreenFunction_HandleBallPhysics: ; 0xd909
+; main loop for stage logic
+ xor a
+ ld [wFlipperCollision], a
+ ld [wd7eb], a
+ call ApplyGravityToBall
+ call LimitBallVelocity
+ xor a
+ ld [wd7e9], a
+ call HandleTilts
+ ld a, [wCurrentStage]
+ bit 0, a
+ callba nz, HandleFlippers ; only perform flipper routines on the lower-half of stages
+ ld a, [wFlipperCollision]
+ and a
+ ld a, [wCollisionForceAngle]
+ push af
+ call CheckObjectCollision ; collision stuff
+ pop af
+ jr z, .noFlipperCollision
+ ld [wCollisionForceAngle], a
+.noFlipperCollision
+ call CheckGameObjectCollisions
+ call Func_281c ; not collision-related
+ ld hl, wKeyConfigMenu
+ call IsKeyPressed
+ jr z, .didntPressMenuKey
+ lb de, $03, $4c
+ call PlaySoundEffect
+ callba HandleInGameMenu
+ jp z, SaveGame
+.didntPressMenuKey
+ ld a, [wd7e9] ; check for collision flag
+ and a
+ jr z, .skip_collision
+ call ApplyTiltForces
+ call LoadBallVelocity ; bc = x velocity, de = y velocity
+ ld a, [wCollisionForceAngle]
+ call ApplyCollisionForce
+ call ApplyTorque
+ ld a, [wFlipperCollision]
+ and a
+ jr z, .not_flippers_2
+ ; de -= *wFlipperYForce
+ ld hl, wFlipperYForce
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, e
+ sub l
+ ld e, a
+ ld a, d
+ sbc h
+ ld d, a
+ ; bc += *wFlipperXForce
+ ld hl, wFlipperXForce
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, c
+ add l
+ ld c, a
+ ld a, b
+ adc h
+ ld b, a
+ jr .next
+
+.not_flippers_2
+ ld a, [wd7f8]
+ and a
+ jr nz, .skip_collision
+.next
+ ld a, [wCollisionForceAngle]
+ call NegateAngleAndApplyCollisionForce
+ call SetBallVelocity
+.skip_collision
+ call MoveBallPosition
+ callba CheckStageTransition
+ callba DrawSpritesForStage
+ call Func_33e3
+ ld a, [wd5cb]
+ and a
+ jr nz, .asm_d9e9
+ callba Func_85c7
+ callba Func_8650
+ callba Func_8645
+ call Func_dba9
+ call Func_dc7c
+ call Func_dcb4
+.asm_d9e9
+ ld a, [wd57d]
+ and a
+ callba nz, Func_86a4
+ ld a, [wd4ae]
+ and a
+ ret z
+ xor a
+ ld [wd4ae], a
+ ld hl, wScreenState
+ inc [hl]
+ ret
+
+INCLUDE "engine/pinball_game/save_game.asm"
+
+GameScreenFunction_HandleBallLoss: ; 0xda36
+ xor a
+ ld [hJoypadState], a
+ ld [hNewlyPressedButtons], a
+ ld [hPressedButtons], a
+ ld [wFlipperCollision], a
+ ld [wd7eb], a
+ xor a
+ ld [wd7e9], a
+ ld [wd548], a
+ ld [wd549], a
+ call HandleTilts
+ ld a, [wCurrentStage]
+ bit 0, a
+ callba nz, HandleFlippers
+ callba DrawSpritesForStage
+ call Func_33e3
+ callba Func_85c7
+ ld a, [wd5ca]
+ and a
+ ret nz
+ ld a, [wd4c9]
+ and a
+ jr z, .asm_daa9
+ ld a, [wd49c]
+ cp $2
+ jr z, .asm_daa9
+ call Func_f533
+ ld a, [wd49c]
+ and a
+ jr z, .asm_daa9
+ ld a, $2
+ ld [wd49c], a
+ ld [wd4aa], a
+ call FillBottomMessageBufferWithBlackTile
+ call Func_30db
+ ld hl, wd5dc
+ ld de, ShootAgainText
+ call LoadTextHeader
+ ret
+
+.asm_daa9
+ xor a
+ ld [wd49c], a
+ ld hl, wScreenState
+ inc [hl]
+ ret
+
+GameScreenFunction_EndBall: ; 0xdab2
+ xor a
+ ld [wd803], a
+ ld a, [wGameOver]
+ and a
+ jp nz, TransitionToHighScoresScreen
+ ld a, [wd495]
+ and a
+ jr nz, .asm_dae6
+ ld a, [wd496]
+ and a
+ jr nz, .asm_db28
+ call Func_cb5
+ ld a, [wd849]
+ and a
+ call z, Func_e5d
+ call Func_576
+ ld hl, hSTAT
+ res 6, [hl]
+ ld hl, rIE
+ res 1, [hl]
+ ld a, $1
+ ld [wScreenState], a
+ ret
+
+.asm_dae6
+ ld de, $0000
+ call PlaySong
+ ld bc, $0004
+ call AdvanceFrames
+ call Func_cb5
+ ld a, [wd849]
+ and a
+ call nz, Func_e5d
+ call Func_576
+ ld hl, hSTAT
+ res 6, [hl]
+ ld hl, rIE
+ res 1, [hl]
+ ld a, [wCurrentStage]
+ ld [wd4ad], a
+ ld a, [wStageCollisionState]
+ ld [wd4b0], a
+ ld a, [wd497]
+ ld [wCurrentStage], a
+ xor a
+ ld [wd496], a
+ ld [wd495], a
+ ld a, $0
+ ld [wScreenState], a
+ ret
+
+.asm_db28
+ ld de, $0000
+ call PlaySong
+ ld bc, $0004
+ call AdvanceFrames
+ call Func_cb5
+ ld a, [wd849]
+ and a
+ call nz, Func_e5d
+ call Func_576
+ ld hl, hSTAT
+ res 6, [hl]
+ ld hl, rIE
+ res 1, [hl]
+ ld a, [wd4ad]
+ ld [wCurrentStage], a
+ ld a, [wd4b0]
+ ld [wStageCollisionState], a
+ ld a, $1
+ ld [wScreenState], a
+ ret
+
+TransitionToHighScoresScreen: ; 0xdb5d
+ xor a
+ ld [wGameOver], a
+ ld de, $0000
+ call PlaySong
+ ld bc, $0004
+ call AdvanceFrames
+ call Func_cb5
+ call Func_576
+ ld hl, hSTAT
+ res 6, [hl]
+ ld hl, rIE
+ res 1, [hl]
+ xor a
+ ld [wd4aa], a
+ ld a, [wCurrentStage]
+ ld c, a
+ ld b, $0
+ ld hl, HighScoresStageMapping
+ add hl, bc
+ ld a, [hl]
+ ld [wHighScoresStage], a
+ ld a, SCREEN_HIGH_SCORES
+ ld [wCurrentScreen], a
+ xor a
+ ld [wScreenState], a
+ ret
+
+HighScoresStageMapping: ; 0xdb99
+; Determines which stage the high scores screen will start in,
+; based on the map the player ended in.
+; See wHighScoresStage for more info.
+ db $00 ; STAGE_RED_FIELD_TOP
+ db $00 ; STAGE_RED_FIELD_BOTTOM
+ db $00
+ db $00
+ db $01 ; STAGE_BLUE_FIELD_TOP
+ db $01 ; STAGE_BLUE_FIELD_BOTTOM
+ db $00 ; STAGE_GENGAR_BONUS
+ db $00 ; STAGE_GENGAR_BONUS
+ db $00 ; STAGE_MEWTWO_BONUS
+ db $00 ; STAGE_MEWTWO_BONUS
+ db $00 ; STAGE_MEOWTH_BONUS
+ db $00 ; STAGE_MEOWTH_BONUS
+ db $00 ; STAGE_DIGLETT_BONUS
+ db $00 ; STAGE_DIGLETT_BONUS
+ db $00 ; STAGE_SEEL_BONUS
+ db $00 ; STAGE_SEEL_BONUS
+
+Func_dba9: ; 0xdba9
+ ld a, $85
+ ld [wBottomMessageBuffer + $44], a
+ ld a, [wd49d]
+ xor $3
+ inc a
+ add $86
+ ld [wBottomMessageBuffer + $45], a
+ ret
diff --git a/engine/pinball_game/ball_loss/ball_loss.asm b/engine/pinball_game/ball_loss/ball_loss.asm
new file mode 100755
index 0000000..06b0cda
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss.asm
@@ -0,0 +1,34 @@
+HandleBallLoss: ; 0xdc49
+ ld a, [wCurrentStage]
+ rst JumpTable ; calls JumpToFuncInTable
+CallTable_dc4d: ; 0xdc4d
+ ; STAGE_RED_FIELD_TOP
+ dw HandleBallLossRedField
+ ; STAGE_RED_FIELD_BOTTOM
+ dw HandleBallLossRedField
+ dw Func_de4e
+ dw Func_de4e
+ ; STAGE_BLUE_FIELD_TOP
+ dw HandleBallLossBlueField
+ ; STAGE_BLUE_FIELD_TOP
+ dw HandleBallLossBlueField
+ ; STAGE_GENGAR_BONUS
+ dw HandleBallLossGengarBonus
+ ; STAGE_GENGAR_BONUS
+ dw HandleBallLossGengarBonus
+ ; STAGE_MEWTWO_BONUS
+ dw HandleBallLossMewtwoBonus
+ ; STAGE_MEWTWO_BONUS
+ dw HandleBallLossMewtwoBonus
+ ; STAGE_MEOWTH_BONUS
+ dw HandleBallLossMeowthBonus
+ ; STAGE_MEOWTH_BONUS
+ dw HandleBallLossMeowthBonus
+ ; STAGE_DIGLETT_BONUS
+ dw HandleBallLossDiglettBonus
+ ; STAGE_DIGLETT_BONUS
+ dw HandleBallLossDiglettBonus
+ ; STAGE_SEEL_BONUS
+ dw HandleBallLossSeelBonus
+ ; STAGE_SEEL_BONUS
+ dw HandleBallLossSeelBonus
diff --git a/engine/pinball_game/ball_loss/ball_loss_blue_field.asm b/engine/pinball_game/ball_loss/ball_loss_blue_field.asm
new file mode 100755
index 0000000..c9bdf10
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss_blue_field.asm
@@ -0,0 +1,93 @@
+HandleBallLossBlueField: ; 0xde4f
+ ld a, [wBallSaverTimerFrames]
+ ld hl, wBallSaverTimerSeconds
+ or [hl]
+ jr z, .youLose
+ ld a, [wNumTimesBallSavedTextWillDisplay]
+ bit 7, a
+ jr nz, .skip_save_text
+ dec a
+ ld [wNumTimesBallSavedTextWillDisplay], a
+ push af
+ ld de, BallSavedText
+ call Func_dc6d
+ pop af
+ jr nz, .skip_save_text
+ ld a, $1
+ ld [wBallSaverTimerFrames], a
+ ld [wBallSaverTimerSeconds], a
+.skip_save_text
+ lb de, $15, $02
+ call PlaySoundEffect
+ ret
+
+.youLose
+ ld de, $0000
+ call PlaySong
+ ld bc, $001e
+ call AdvanceFrames
+ lb de, $25, $24
+ call PlaySoundEffect
+ call Start20SecondSaverTimer
+ ld a, $1
+ ld [wd4c9], a
+ xor a
+ ld [wd4de], a
+ ld [wd4df], a
+ call Func_ded6
+ ld a, [wd49b]
+ and a
+ jr z, .asm_deb6
+ dec a
+ ld [wd49b], a
+ ld a, $1
+ ld [wd49c], a
+ ld de, EndOfBallBonusText
+ call Func_dc6d
+ ret
+
+.asm_deb6
+ ld a, [wd49d]
+ ld hl, wd49e
+ cp [hl]
+ jr z, .asm_deca
+ inc a
+ ld [wd49d], a
+ ld de, EndOfBallBonusText
+ call Func_dc6d
+ ret
+
+.asm_deca
+ ld de, EndOfBallBonusText
+ call Func_dc6d
+ ld a, $1
+ ld [wGameOver], a
+ ret
+
+Func_ded6: ; 0xded6
+ ld a, [wInSpecialMode]
+ and a
+ ret z
+ ld a, [wSpecialMode]
+ and a
+ jr nz, .asm_deec
+ callba Func_10157
+ ret
+
+.asm_deec
+ cp $1
+ jr nz, .asm_df05
+ ld a, $0
+ ld [wd604], a
+ ld a, $1e
+ ld [wd607], a
+ callba Func_10ac8
+ ret
+
+.asm_df05
+ ld a, $0
+ ld [wd604], a
+ ld a, $1e
+ ld [wd607], a
+ callba Func_3022b
+ ret
diff --git a/engine/pinball_game/ball_loss/ball_loss_diglett_bonus.asm b/engine/pinball_game/ball_loss/ball_loss_diglett_bonus.asm
new file mode 100755
index 0000000..7e9fdf9
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss_diglett_bonus.asm
@@ -0,0 +1,24 @@
+HandleBallLossDiglettBonus: ; 0xe056
+ ld a, [wd4ad]
+ ld hl, wCurrentStage
+ cp [hl]
+ ret z
+ lb de, $00, $0b
+ call PlaySoundEffect
+ xor a
+ ld [wd495], a
+ ld a, $1
+ ld [wd496], a
+ ld a, $2
+ ld [wd4c8], a
+ xor a
+ ld [wd7ac], a
+ ld a, [wd49a]
+ and a
+ ret nz
+ call FillBottomMessageBufferWithBlackTile
+ call Func_30db
+ ld hl, wd5dc
+ ld de, EndDiglettStageText
+ call LoadTextHeader
+ ret
diff --git a/engine/pinball_game/ball_loss/ball_loss_gengar_bonus.asm b/engine/pinball_game/ball_loss/ball_loss_gengar_bonus.asm
new file mode 100755
index 0000000..2ba10d0
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss_gengar_bonus.asm
@@ -0,0 +1,50 @@
+HandleBallLossGengarBonus: ; 0xdf1a
+ ld a, [wd4ad]
+ ld hl, wCurrentStage
+ cp [hl]
+ ret z
+ ld a, [wd6a8]
+ and a
+ jr nz, .asm_df57
+ ld a, [wd6a2]
+ cp $5
+ jr c, .asm_df50
+ xor a
+ ld [wd4ae], a
+ ld a, [wd6a7]
+ and a
+ ret nz
+ ld [wd548], a
+ ld [wd549], a
+ ld [wBallSpin], a
+ ld [wBallRotation], a
+ ld hl, wBallXVelocity
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld a, $1
+ ld [wd6a7], a
+.asm_df50
+ lb de, $00, $02
+ call PlaySoundEffect
+ ret
+
+.asm_df57
+ xor a
+ ld [wd495], a
+ ld a, $1
+ ld [wd496], a
+ ld a, $2
+ ld [wd4c8], a
+ xor a
+ ld [wd7ac], a
+ ld a, [wd49a]
+ and a
+ ret nz
+ call FillBottomMessageBufferWithBlackTile
+ call Func_30db
+ ld hl, wd5dc
+ ld de, EndGengarStageText
+ call LoadTextHeader
+ ret
diff --git a/engine/pinball_game/ball_loss/ball_loss_meowth_bonus.asm b/engine/pinball_game/ball_loss/ball_loss_meowth_bonus.asm
new file mode 100755
index 0000000..c5366c8
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss_meowth_bonus.asm
@@ -0,0 +1,57 @@
+HandleBallLossMeowthBonus: ; 0xdfe2
+ xor a
+ ld [wd64e], a
+ ld a, [wd7be]
+ and a
+ jr z, .asm_dff2
+ ld a, [wd49a]
+ and a
+ jr z, .asm_e00f
+.asm_dff2
+ ld a, [wMeowthStageScore]
+ cp 20
+ jr nc, .asm_e00f
+ cp 5
+ jr c, .asm_e001
+ sub $4
+ jr .asm_e002
+
+.asm_e001
+ xor a
+.asm_e002
+ ld [wMeowthStageScore], a
+ callba Func_24fa3
+.asm_e00f
+ ld a, [wd4ad]
+ ld hl, wCurrentStage
+ cp [hl]
+ ret z
+ ld a, [wd712]
+ cp $0
+ jr nz, .asm_e025
+ lb de, $00, $02
+ call PlaySoundEffect
+ ret
+
+.asm_e025
+ xor a
+ ld [wd57e], a
+ ld [wd57d], a
+ xor a
+ ld [wd495], a
+ ld a, $1
+ ld [wd496], a
+ ld a, $2
+ ld [wd4c8], a
+ xor a
+ ld [wd7ac], a
+ ld [wd712], a
+ ld a, [wd49a]
+ and a
+ ret nz
+ call FillBottomMessageBufferWithBlackTile
+ call Func_30db
+ ld hl, wd5dc
+ ld de, EndMeowthStageText
+ call LoadTextHeader
+ ret
diff --git a/engine/pinball_game/ball_loss/ball_loss_mewtwo_bonus.asm b/engine/pinball_game/ball_loss/ball_loss_mewtwo_bonus.asm
new file mode 100755
index 0000000..95d1b5d
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss_mewtwo_bonus.asm
@@ -0,0 +1,50 @@
+HandleBallLossMewtwoBonus: ; 0xdf7e
+ ld a, [wd4ad]
+ ld hl, wCurrentStage
+ cp [hl]
+ ret z
+ ld a, [wd6b3]
+ and a
+ jr nz, .asm_dfbb
+ ld a, [wd6b1]
+ cp $8
+ jr c, .asm_dfb4
+ xor a
+ ld [wd4ae], a
+ ld a, [wd6b2]
+ and a
+ ret nz
+ ld [wd548], a
+ ld [wd549], a
+ ld [wBallSpin], a
+ ld [wBallRotation], a
+ ld hl, wBallXVelocity
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld a, $1
+ ld [wd6b2], a
+.asm_dfb4
+ lb de, $00, $0b
+ call PlaySoundEffect
+ ret
+
+.asm_dfbb
+ xor a
+ ld [wd495], a
+ ld a, $1
+ ld [wd496], a
+ ld a, $2
+ ld [wd4c8], a
+ xor a
+ ld [wd7ac], a
+ ld a, [wd49a]
+ and a
+ ret nz
+ call FillBottomMessageBufferWithBlackTile
+ call Func_30db
+ ld hl, wd5dc
+ ld de, EndMewtwoStageText
+ call LoadTextHeader
+ ret
diff --git a/engine/pinball_game/ball_loss/ball_loss_red_field.asm b/engine/pinball_game/ball_loss/ball_loss_red_field.asm
new file mode 100755
index 0000000..6889022
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss_red_field.asm
@@ -0,0 +1,104 @@
+HandleBallLossRedField: ; 0xdd76
+ ld a, [wBallSaverTimerFrames]
+ ld hl, wBallSaverTimerSeconds
+ or [hl]
+ jr z, .youLose
+ ld a, [wNumTimesBallSavedTextWillDisplay]
+ bit 7, a
+ jr nz, .skip_save_text
+ dec a
+ ld [wNumTimesBallSavedTextWillDisplay], a
+ push af
+ ld de, BallSavedText
+ call Func_dc6d
+ pop af
+ jr nz, .skip_save_text
+ ld a, $1
+ ld [wBallSaverTimerFrames], a
+ ld [wBallSaverTimerSeconds], a
+.skip_save_text
+ lb de, $15, $02
+ call PlaySoundEffect
+ ret
+
+.youLose
+ ld de, $0000
+ call PlaySong
+ ld bc, $001e
+ call AdvanceFrames
+ lb de, $25, $24
+ call PlaySoundEffect
+ call Start20SecondSaverTimer
+ ld a, $1
+ ld [wd4c9], a
+ xor a
+ ld [wd4de], a
+ ld [wd4df], a
+ call Func_ddfd
+ ld a, [wd49b]
+ and a
+ jr z, .asm_dddd
+ dec a
+ ld [wd49b], a
+ ld a, $1
+ ld [wd49c], a
+ ld de, EndOfBallBonusText
+ call Func_dc6d
+ ret
+
+.asm_dddd
+ ld a, [wd49d]
+ ld hl, wd49e
+ cp [hl]
+ jr z, .asm_ddf1
+ inc a
+ ld [wd49d], a
+ ld de, EndOfBallBonusText
+ call Func_dc6d
+ ret
+
+.asm_ddf1
+ ld de, EndOfBallBonusText
+ call Func_dc6d
+ ld a, $1
+ ld [wGameOver], a
+ ret
+
+Func_ddfd: ; 0xddfd
+ ld a, [wInSpecialMode]
+ and a
+ ret z
+ ld a, [wSpecialMode]
+ and a
+ jr nz, .asm_de14
+ callba Func_10157
+ jr .asm_de40
+
+.asm_de14
+ cp $1
+ jr nz, .asm_de2d
+ xor a
+ ld [wd604], a
+ ld a, $1e
+ ld [wd607], a
+ callba Func_10ac8
+ jr .asm_de40
+
+.asm_de2d
+ xor a
+ ld [wd604], a
+ ld a, $1e
+ ld [wd607], a
+ callba Func_3022b
+.asm_de40
+ ld a, [wd7ad]
+ ld c, a
+ ld a, [wStageCollisionState]
+ and $1
+ or c
+ ld [wStageCollisionState], a
+ ret
+
+Func_de4e: ; 0xde4e
+; unused
+ ret
diff --git a/engine/pinball_game/ball_loss/ball_loss_seel_bonus.asm b/engine/pinball_game/ball_loss/ball_loss_seel_bonus.asm
new file mode 100755
index 0000000..7db2efe
--- /dev/null
+++ b/engine/pinball_game/ball_loss/ball_loss_seel_bonus.asm
@@ -0,0 +1,56 @@
+HandleBallLossSeelBonus: ; 0xe08b
+ xor a
+ ld [wd64e], a
+ ld a, [wd7be]
+ and a
+ jr z, .asm_e09b
+ ld a, [wd49a]
+ and a
+ jr z, .asm_e0b8
+.asm_e09b
+ ld a, [wd793]
+ cp $14
+ jr nc, .asm_e0b8
+ cp $5
+ jr c, .asm_e0aa
+ sub $4
+ jr .asm_e0ab
+
+.asm_e0aa
+ xor a
+.asm_e0ab
+ ld [wd793], a
+ callba Func_262f4
+.asm_e0b8
+ ld a, [wd4ad]
+ ld hl, wCurrentStage
+ cp [hl]
+ ret z
+ ld a, [wd794]
+ cp $0
+ jr nz, .asm_e0c8
+ ret
+
+.asm_e0c8
+ lb de, $00, $02
+ call PlaySoundEffect
+ xor a
+ ld [wd57d], a
+ ld [wd57d], a
+ ld [wd495], a
+ ld a, $1
+ ld [wd496], a
+ ld a, $2
+ ld [wd4c8], a
+ xor a
+ ld [wd7ac], a
+ ld [wd794], a
+ ld a, [wd49a]
+ and a
+ ret nz
+ call FillBottomMessageBufferWithBlackTile
+ call Func_30db
+ ld hl, wd5dc
+ ld de, EndSeelStageText
+ call LoadTextHeader
+ ret
diff --git a/engine/pinball_game/flippers.asm b/engine/pinball_game/flippers.asm
new file mode 100755
index 0000000..466975e
--- /dev/null
+++ b/engine/pinball_game/flippers.asm
@@ -0,0 +1,772 @@
+HandleFlippers: ; 0xe0fe
+ xor a
+ ld [wFlipperCollision], a
+ ld [hFlipperYCollisionAttribute], a
+ ld [wFlipperXForce], a
+ ld [wFlipperXForce + 1], a
+ call Func_e118
+ call CheckFlipperCollision
+ ld a, [wFlipperCollision]
+ and a
+ call nz, HandleFlipperCollision
+ ret
+
+Func_e118: ; 0xe118
+ call PlayFlipperSoundIfPressed
+ ld a, [wd7af]
+ ld [wLeftFlipperAnimationState], a
+ ld a, [wd7b3]
+ ld [wRightFlipperAnimationState], a
+ ld hl, wKeyConfigLeftFlipper
+ call IsKeyPressed2
+ ld hl, -$0333
+ jr z, .asm_e13b
+ ld a, [wd7be]
+ and a
+ jr nz, .asm_e13b
+ ld hl, $0333
+.asm_e13b
+ ld a, [wd7af]
+ and a
+ jr nz, .asm_e145
+ bit 7, h
+ jr nz, .asm_e14d
+.asm_e145
+ cp $f
+ jr nz, .asm_e150
+ bit 7, h
+ jr nz, .asm_e150
+.asm_e14d
+ ld hl, $0000
+.asm_e150
+ ld a, l
+ ld [wd7b0], a
+ ld a, h
+ ld [wd7b1], a
+ ld a, [wd7ae]
+ ld c, a
+ ld a, [wd7af]
+ ld b, a
+ add hl, bc
+ bit 7, h
+ jr nz, .asm_e16f
+ ld a, h
+ cp $10
+ jr c, .asm_e172
+ ld hl, $0f00
+ jr .asm_e172
+
+.asm_e16f
+ ld hl, $0000
+.asm_e172
+ ld a, l
+ ld [wd7ae], a
+ ld a, h
+ ld [wd7af], a
+ ld hl, wKeyConfigRightFlipper
+ call IsKeyPressed2
+ ld hl, -$0333
+ jr z, .asm_e18e
+ ld a, [wd7be]
+ and a
+ jr nz, .asm_e18e
+ ld hl, $0333
+.asm_e18e
+ ld a, [wd7b3]
+ and a
+ jr nz, .asm_e198
+ bit 7, h
+ jr nz, .asm_e1a0
+.asm_e198
+ cp $f
+ jr nz, .asm_e1a3
+ bit 7, h
+ jr nz, .asm_e1a3
+.asm_e1a0
+ ld hl, $0000
+.asm_e1a3
+ ld a, l
+ ld [wd7b4], a
+ ld a, h
+ ld [wd7b5], a
+ ld a, [wd7b2]
+ ld c, a
+ ld a, [wd7b3]
+ ld b, a
+ add hl, bc
+ bit 7, h
+ jr nz, .asm_e1c2
+ ld a, h
+ cp $10
+ jr c, .asm_e1c5
+ ld hl, $0f00
+ jr .asm_e1c5
+
+.asm_e1c2
+ ld hl, $0000
+.asm_e1c5
+ ld a, l
+ ld [wd7b2], a
+ ld a, h
+ ld [wd7b3], a
+ ret
+
+PlayFlipperSoundIfPressed: ; 0xe1ce
+ ld a, [wd7be]
+ and a
+ ret nz
+ ld hl, wKeyConfigLeftFlipper
+ call IsKeyPressed
+ jr z, .asm_e1e2
+ lb de, $00, $0c
+ call PlaySoundEffect
+ ret
+
+.asm_e1e2
+ ld hl, wKeyConfigRightFlipper
+ call IsKeyPressed
+ ret z
+ lb de, $00, $0c
+ call PlaySoundEffect
+ ret
+
+CheckFlipperCollision: ; 0xe1f0
+ ld a, [wBallXPos + 1]
+ cp $50 ; which half of the screen is the ball in?
+ jp nc, CheckRightFlipperCollision ; right half of screen
+ ; fall through
+CheckLeftFlipperCollision:
+ ld hl, wBallXPos
+ ld c, $ba
+ ld a, [hli]
+ ld [$ff00+c], a
+ inc c
+ ld a, [hli]
+ ld [$ff00+c], a
+ inc c
+ ld a, [hli]
+ ld [$ff00+c], a
+ inc c
+ ld a, [hli]
+ ld [$ff00+c], a
+ inc c
+ ld a, [wLeftFlipperAnimationState]
+ ld [$ffc2], a
+ ld a, [wd7af]
+ ld [$ffc3], a
+ call ReadFlipperCollisionAttributes
+ ld a, [wFlipperCollision]
+ and a
+ ret z
+ ld a, [wd7b0]
+ ld [$ffc0], a
+ ld a, [wd7b1]
+ ld [$ffc1], a
+ ret
+
+CheckRightFlipperCollision: ; 0xe226
+; ball is in right half of screen
+ ld hl, wBallXPos
+ ld c, $ba
+ ld a, [hli]
+ sub $1
+ cpl
+ ld [$ff00+c], a
+ inc c
+ ld a, [hli]
+ sbc $a0
+ cpl
+ ld [$ff00+c], a
+ inc c
+ ld a, [hli]
+ ld [$ff00+c], a
+ inc c
+ ld a, [hli]
+ ld [$ff00+c], a
+ inc c
+ ld a, [wRightFlipperAnimationState]
+ ld [$ffc2], a
+ ld a, [wd7b3]
+ ld [$ffc3], a
+ call ReadFlipperCollisionAttributes
+ ld a, [wFlipperCollision]
+ and a
+ ret z
+ ; collision with flipper occurred
+ ld a, [wd7b4]
+ ld [$ffc0], a
+ ld a, [wd7b5]
+ ld [$ffc1], a
+ ret
+
+ReadFlipperCollisionAttributes: ; 0xe25a
+ ld a, [$ffbb] ; ball x-position high byte
+ sub $2b ; check if ball is in x-position range of flippers
+ ret c
+ cp $30
+ ret nc
+ ; ball is in x-position range of flippers
+ ld [$ffbb], a ; x offset of flipper horizontal range
+ ld a, [$ffbd] ; ball y-position high byte
+ sub $7b ; check if ball is in y-position range of flippers
+ ret c
+ cp $20
+ ret nc
+ ; ball is in potential collision with flippers
+ ld [$ffbd], a ; y offset of flipper vertical range
+ ld a, [$ffc2] ; flipper animation state
+.asm_e270
+ push af
+ ld l, $0
+ ld h, a ; multiply a by 0x600
+ sla a
+ sla h
+ sla h
+ add h
+ ld h, a ; hl = a * 0x600 (this is the length of the flipper collision attributes)
+ ld a, [$ffbb] ; x offset of flipper horizontal range
+ ld c, a
+ ld b, $0
+ sla c
+ rl b
+ sla c
+ rl b
+ sla c
+ rl b
+ sla c
+ rl b
+ sla c
+ rl b ; bc = (x offset of flipper horizontal range) * 32
+ ; Each row of the flipper collision attributes is 32 bytes long.
+ add hl, bc ; hl points to the start of the row in the flipper collisoin attributes
+ ld a, [$ffbd] ; y offset of flipper vertical range
+ ld c, a
+ ld b, $0
+ add hl, bc ; hl points to the attribute byte in the flipper collision attributes
+ ld d, h
+ ld e, l ; de points to the attribute byte in the flipper collision attributes
+ ld a, h
+ cp $40
+ jr nc, .secondBank
+ add $40
+ ld h, a
+ ld a, Bank(FlipperHorizontalCollisionAttributes)
+ jr .readAttributeByte
+
+.secondBank
+ ld a, Bank(FlipperHorizontalCollisionAttributes2)
+.readAttributeByte
+ call ReadByteFromBank
+ ld b, a
+ and a
+ jr nz, .collision
+ ; no collision
+ pop af ; a = flipper animation state(?)
+ ld hl, $ffc3
+ cp [hl]
+ ret z
+ jr c, .asm_e2be
+ dec a
+ jr .asm_e270
+
+.asm_e2be
+ inc a
+ jr .asm_e270
+
+.collision
+ pop af ; a = flipper animation state(?)
+ ld a, b ; a = collision attribute
+ ld [hFlipperYCollisionAttribute], a
+ ld h, d
+ ld l, e
+ ld a, h
+ cp $20
+ jr nc, .asm_e2d3
+ add $60
+ ld h, a
+ ld a, Bank(FlipperVerticalCollisionAttributes)
+ jr .asm_e2d8
+
+.asm_e2d3
+ add $20
+ ld h, a
+ ld a, Bank(FlipperVerticalCollisionAttributes2)
+.asm_e2d8
+ call ReadByteFromBank
+ ld [wFlipperXCollisionAttribute], a
+ ld a, $1
+ ld [wFlipperCollision], a
+ ret
+
+Func_e2e4:
+ ld a, c
+ or b
+ or l
+ or h
+ or e
+ or d
+ jr nz, .asm_e2f3
+ ld a, [$ffba]
+ ld e, a
+ ld a, [$ffbb]
+ ld d, a
+ ret
+
+.asm_e2f3
+ ld a, d
+ xor h
+ push af
+ bit 7, d
+ jr z, .asm_e301
+ ld a, e
+ cpl
+ ld e, a
+ ld a, d
+ cpl
+ ld d, a
+ inc de
+.asm_e301
+ bit 7, h
+ jr z, .asm_e317
+ ld a, c
+ cpl
+ ld c, a
+ ld a, b
+ cpl
+ ld b, a
+ ld a, l
+ cpl
+ ld l, a
+ ld a, h
+ cpl
+ ld h, a
+ inc bc
+ ld a, b
+ or c
+ jr nz, .asm_e317
+ inc hl
+.asm_e317
+ push bc
+ ld c, $11
+ ld a, d
+ or e
+ jr nz, .asm_e324
+ pop bc
+ ld de, $7fff
+ jr .asm_e36a
+
+.asm_e324
+ bit 7, d
+ jr nz, .asm_e32f
+ sla e
+ rl d
+ inc c
+ jr .asm_e324
+
+.asm_e32f
+ ld a, c
+ ld [$ff8c], a
+ pop bc
+ xor a
+ ld [$ff8d], a
+ ld [$ff8e], a
+.asm_e338
+ jr c, .asm_e344
+ ld a, d
+ cp h
+ jr nz, .asm_e342
+ ld a, e
+ cp l
+ jr z, .asm_e344
+.asm_e342
+ jr nc, .asm_e34b
+.asm_e344
+ ld a, l
+ sub e
+ ld l, a
+ ld a, h
+ sbc d
+ ld h, a
+ scf
+.asm_e34b
+ ld a, [$ff8d]
+ rla
+ ld [$ff8d], a
+ ld a, [$ff8e]
+ rla
+ ld [$ff8e], a
+ sla c
+ rl b
+ rl l
+ rl h
+ ld a, [$ff8c]
+ dec a
+ ld [$ff8c], a
+ jr nz, .asm_e338
+ ld a, [$ff8d]
+ ld e, a
+ ld a, [$ff8e]
+ ld d, a
+.asm_e36a
+ pop af
+ bit 7, a
+ ret z
+ ld a, e
+ sub $1
+ cpl
+ ld e, a
+ ld a, d
+ sbc $0
+ cpl
+ ld d, a
+ ret
+
+Func_e379: ; 0xe379
+ ld a, b
+ xor d
+ ld [$ffbe], a
+ bit 7, b
+ jr z, .asm_e388
+ ld a, c
+ cpl
+ ld c, a
+ ld a, b
+ cpl
+ ld b, a
+ inc bc
+.asm_e388
+ bit 7, d
+ jr z, .asm_e393
+ ld a, e
+ cpl
+ ld e, a
+ ld a, d
+ cpl
+ ld d, a
+ inc de
+.asm_e393
+ push bc
+ push de
+ ld c, d
+ call Func_e410
+ pop de
+ pop bc
+ push hl
+ push bc
+ push de
+ ld c, e
+ call Func_e410
+ pop de
+ pop bc
+ push hl
+ push bc
+ push de
+ ld b, d
+ call Func_e410
+ pop de
+ pop bc
+ push hl
+ ld b, e
+ call Func_e410
+ ld c, l
+ ld l, h
+ xor a
+ ld h, a
+ pop de
+ add hl, de
+ rl a
+ pop de
+ add hl, de
+ jr nc, .asm_e3bf
+ inc a
+.asm_e3bf
+ ld b, l
+Data_e3c0:
+ ld l, h
+ ld h, a
+ pop de
+ add hl, de
+ ld a, [$ffbe]
+ bit 7, a
+ ret z
+ ld a, c
+ sub $1
+ cpl
+ ld c, a
+ ld a, b
+ sbc $0
+ cpl
+ ld b, a
+ ld a, l
+ sbc $0
+ cpl
+ ld l, a
+ ld a, h
+ sbc $0
+ cpl
+ ld h, a
+ ret
+
+Func_e3de:
+ push bc
+ push de
+ ld c, d
+ call Func_e410
+ pop de
+ pop bc
+ push hl
+ push bc
+ push de
+ ld c, e
+ call Func_e410
+ pop de
+ pop bc
+ push hl
+ push bc
+ push de
+ ld b, d
+ call Func_e410
+ pop de
+ pop bc
+ push hl
+ ld b, e
+ call Func_e410
+ ld c, l
+ ld l, h
+ xor a
+ ld h, a
+ pop de
+ add hl, de
+ rl a
+ pop de
+ add hl, de
+ jr nc, .asm_e40a
+ inc a
+.asm_e40a
+ ld b, l
+ ld l, h
+ ld h, a
+ pop de
+ add hl, de
+ ret
+
+Func_e410: ; 0xe410
+ ld a, b
+ cp c
+ jr nc, .asm_e416
+ ld b, c
+ ld c, a
+.asm_e416
+ ld h, $3e
+ ld l, c
+ ld e, [hl]
+ inc h
+ ld d, [hl]
+ ld l, b
+ ld a, [hl]
+ dec h
+ ld l, [hl]
+ ld h, a
+ add hl, de
+ push af
+ ld d, $3e
+ ld a, b
+ sub c
+ ld e, a
+ ld a, [de]
+ ld c, a
+ inc d
+ ld a, [de]
+ ld b, a
+ ld a, l
+ sub c
+ ld l, a
+ ld a, h
+ sbc b
+ ld h, a
+ jr nc, .asm_e43c
+ pop af
+ ccf
+ rr h
+ rr l
+ ret
+
+.asm_e43c
+ pop af
+ rr h
+ rr l
+ ret
+
+HandleFlipperCollision: ; 0xe442
+; This is called when the ball is colliding with either the
+; right or left flipper.
+ ld a, $1
+ ld [wd7e9], a
+ xor a
+ ld [wBallPositionPointerOffsetFromStageTopLeft], a
+ ld [wBallPositionPointerOffsetFromStageTopLeft + 1], a
+ ld [wCurCollisionAttribute], a
+ ld [wd7f6], a
+ ld [wd7f7], a
+ ld a, [hFlipperYCollisionAttribute]
+ sla a
+ ld c, a
+ ld b, $0
+ ld hl, Data_e538
+ add hl, bc
+ ld a, [hli]
+ ld c, a
+ ld a, [hl]
+ ld b, a
+ ld a, [$ffc0]
+ ld e, a
+ ld a, [$ffc1]
+ ld d, a
+ sla e
+ rl d
+ sla e
+ rl d ; multiplied de by 4
+ call Func_e379
+ ld a, b
+ ld [wFlipperYForce], a
+ ld a, l
+ ld [wFlipperYForce + 1], a
+ ld a, [wBallXPos + 1]
+ cp $50 ; which flipper did the ball hit?
+ ld a, [wFlipperXCollisionAttribute]
+ jr c, .asm_e48b
+ cpl ; invert the x collision attribute
+ inc a
+.asm_e48b
+ ld [wCollisionForceAngle], a
+ ld a, $1
+ ld [wd7eb], a
+ ld a, [wFlipperYForce + 1]
+ bit 7, a
+ ret z
+ xor a
+ ld [wFlipperYForce], a
+ ld [wFlipperYForce + 1], a
+ ret
+
+DrawFlippers: ; 0xe4a1
+ ld a, [wCurrentStage]
+ and a
+ ret z
+ ld hl, FlippersOAMPixelOffsetData
+ ld a, [hSCX]
+ ld d, a
+ ld a, [hSCY]
+ ld e, a
+ ld a, [hli]
+ sub d
+ ld b, a
+ ld a, [hli]
+ sub e
+ ld c, a
+ push hl
+ ld hl, LeftFlipperOAMIds
+ ld a, [wd7af]
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld a, [hl]
+ cp $b
+ jr nz, .asm_e4d6
+ ld a, [hGameBoyColorFlag]
+ and a
+ jr nz, .asm_e4d4
+ ld a, [wd7be]
+ and a
+ jr z, .asm_e4d4
+ ld a, $18
+ jr .asm_e4d6
+
+.asm_e4d4
+ ld a, $b
+.asm_e4d6
+ call LoadOAMData
+ pop hl
+ ld a, [hSCX]
+ ld d, a
+ ld a, [hSCY]
+ ld e, a
+ ld a, [hli]
+ sub d
+ ld b, a
+ ld a, [hli]
+ sub e
+ ld c, a
+ ld hl, RightFlipperOAMIds
+ ld a, [wd7b3]
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld a, [hl]
+ cp $8
+ jr nz, .asm_e506
+ ld a, [hGameBoyColorFlag]
+ and a
+ jr nz, .asm_e504
+ ld a, [wd7be]
+ and a
+ jr z, .asm_e504
+ ld a, $17
+ jr .asm_e506
+
+.asm_e504
+ ld a, $8
+.asm_e506
+ call LoadOAMData
+ ret
+
+FlippersOAMPixelOffsetData:
+; flipper oam pixel offsets
+ dw $7b38 ; left flipper
+ dw $7b68 ; right flipper
+
+LeftFlipperOAMIds:
+; TODO: Don't know how exactly these are used, but it is used by the animation
+; when the flipper is activated and rotates upward to hit the pinball.
+ db $0b, $0b, $0b, $0b, $0b, $0b, $0b
+ db $0c, $0c, $0c, $0c, $0c, $0c, $0c
+ db $0d, $0d, $0d, $0d, $0d, $0d, $0d
+
+RightFlipperOAMIds:
+ db $08, $08, $08, $08, $08, $08, $08
+ db $09, $09, $09, $09, $09, $09, $09
+ db $0A, $0A, $0A, $0A, $0A, $0A, $0A
+
+Data_e538: ; 0xe538
+ dw $0000
+ dw $000C
+ dw $001C
+ dw $0030
+ dw $0038
+ dw $0048
+ dw $005C
+ dw $006C
+ dw $0070
+ dw $0080
+ dw $0094
+ dw $00A4
+ dw $00B4
+ dw $00C4
+ dw $00D4
+ dw $00E4
+ dw $00F8
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
+ dw $00FC
diff --git a/engine/pinball_game/save_game.asm b/engine/pinball_game/save_game.asm
new file mode 100755
index 0000000..e9d5e8f
--- /dev/null
+++ b/engine/pinball_game/save_game.asm
@@ -0,0 +1,21 @@
+SaveGame: ; 0xda05
+ ld de, $0000
+ call PlaySong
+ ld bc, $0004
+ call AdvanceFrames
+ call Func_cb5
+ ld a, [wd849]
+ and a
+ call nz, Func_e5d
+ call Func_576
+ ld hl, hSTAT
+ res 6, [hl]
+ ld hl, rIE
+ res 1, [hl]
+ xor a
+ ld [wd4aa], a
+ ld a, SCREEN_TITLESCREEN
+ ld [wCurrentScreen], a
+ xor a
+ ld [wScreenState], a
+ ret
diff --git a/engine/pinball_game/stage_init/init_stages.asm b/engine/pinball_game/stage_init/init_stages.asm
index 948919f..d59df02 100755
--- a/engine/pinball_game/stage_init/init_stages.asm
+++ b/engine/pinball_game/stage_init/init_stages.asm
@@ -1,4 +1,4 @@
-InitializeStage: ; 0x8311
+InitializeCurrentStage: ; 0x8311
ld hl, wc000
ld bc, $0a00
call ClearData
diff --git a/main.asm b/main.asm
index 5b520f7..dbc7e2b 100755
--- a/main.asm
+++ b/main.asm
@@ -1676,369 +1676,6 @@ INCLUDE "engine/high_scores_screen.asm"
INCLUDE "engine/field_select_screen.asm"
INCLUDE "engine/pinball_game.asm"
-GameScreenFunction_LoadGFX: ; 0xd861
- xor a
- ld [wd908], a
- callba InitializeStage
- call FillBottomMessageBufferWithBlackTile
- ld a, $1
- ld [wd85d], a
- ld [wd4aa], a
- ld hl, wScreenState
- inc [hl]
- ret
-
-GameScreenFunction_StartBall: ; 0xd87f
- ld a, $67
- ld [hLCDC], a
- ld a, $e4
- ld [wBGP], a
- ld a, $e1
- ld [wOBP0], a
- ld a, $e4
- ld [wOBP1], a
- ld a, [wSCX]
- ld [hSCX], a
- xor a
- ld [hSCY], a
- ld a, $7
- ld [hWX], a
- ld a, $83
- ld [hLYC], a
- ld [hLastLYC], a
- ld a, $ff
- ld [hLCDCMask], a
- ld hl, hSTAT
- set 6, [hl]
- ld hl, rIE
- set 1, [hl]
- ld a, $1
- ld [hHBlankRoutine], a
- callba InitBallForStage
- callba LoadStageCollisionAttributes
- callba LoadStageData
- callba Func_ed5e
- call ClearOAMBuffer
- callba DrawSpritesForStage
- ld a, [wd849]
- and a
- call nz, Func_e5d
- ld a, $1
- ld [wd4aa], a
- xor a
- ld [wd7c1], a
- call Func_b66
- call Func_588
- call Func_bbe
- ld hl, wScreenState
- inc [hl]
- ret
-
-GameScreenFunction_HandleBallPhysics: ; 0xd909
-; main loop for stage logic
- xor a
- ld [wFlipperCollision], a
- ld [wd7eb], a
- call ApplyGravityToBall
- call LimitBallVelocity
- xor a
- ld [wd7e9], a
- call HandleTilts
- ld a, [wCurrentStage]
- bit 0, a
- callba nz, HandleFlippers ; only perform flipper routines on the lower-half of stages
- ld a, [wFlipperCollision]
- and a
- ld a, [wCollisionForceAngle]
- push af
- call CheckObjectCollision ; collision stuff
- pop af
- jr z, .noFlipperCollision
- ld [wCollisionForceAngle], a
-.noFlipperCollision
- call CheckGameObjectCollisions
- call Func_281c ; not collision-related
- ld hl, wKeyConfigMenu
- call IsKeyPressed
- jr z, .didntPressMenuKey
- lb de, $03, $4c
- call PlaySoundEffect
- callba HandleInGameMenu
- jp z, SaveGame
-.didntPressMenuKey
- ld a, [wd7e9] ; check for collision flag
- and a
- jr z, .skip_collision
- call ApplyTiltForces
- call LoadBallVelocity ; bc = x velocity, de = y velocity
- ld a, [wCollisionForceAngle]
- call ApplyCollisionForce
- call ApplyTorque
- ld a, [wFlipperCollision]
- and a
- jr z, .not_flippers_2
- ; de -= *wFlipperYForce
- ld hl, wFlipperYForce
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, e
- sub l
- ld e, a
- ld a, d
- sbc h
- ld d, a
- ; bc += *wFlipperXForce
- ld hl, wFlipperXForce
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, c
- add l
- ld c, a
- ld a, b
- adc h
- ld b, a
- jr .next
-
-.not_flippers_2
- ld a, [wd7f8]
- and a
- jr nz, .skip_collision
-.next
- ld a, [wCollisionForceAngle]
- call NegateAngleAndApplyCollisionForce
- call SetBallVelocity
-.skip_collision
- call MoveBallPosition
- callba CheckStageTransition
- callba DrawSpritesForStage
- call Func_33e3
- ld a, [wd5cb]
- and a
- jr nz, .asm_d9e9
- callba Func_85c7
- callba Func_8650
- callba Func_8645
- call Func_dba9
- call Func_dc7c
- call Func_dcb4
-.asm_d9e9
- ld a, [wd57d]
- and a
- callba nz, Func_86a4
- ld a, [wd4ae]
- and a
- ret z
- xor a
- ld [wd4ae], a
- ld hl, wScreenState
- inc [hl]
- ret
-
-SaveGame: ; 0xda05
- ld de, $0000
- call PlaySong
- ld bc, $0004
- call AdvanceFrames
- call Func_cb5
- ld a, [wd849]
- and a
- call nz, Func_e5d
- call Func_576
- ld hl, hSTAT
- res 6, [hl]
- ld hl, rIE
- res 1, [hl]
- xor a
- ld [wd4aa], a
- ld a, SCREEN_TITLESCREEN
- ld [wCurrentScreen], a
- xor a
- ld [wScreenState], a
- ret
-
-GameScreenFunction_HandleBallLoss: ; 0xda36
- xor a
- ld [hJoypadState], a
- ld [hNewlyPressedButtons], a
- ld [hPressedButtons], a
- ld [wFlipperCollision], a
- ld [wd7eb], a
- xor a
- ld [wd7e9], a
- ld [wd548], a
- ld [wd549], a
- call HandleTilts
- ld a, [wCurrentStage]
- bit 0, a
- callba nz, HandleFlippers
- callba DrawSpritesForStage
- call Func_33e3
- callba Func_85c7
- ld a, [wd5ca]
- and a
- ret nz
- ld a, [wd4c9]
- and a
- jr z, .asm_daa9
- ld a, [wd49c]
- cp $2
- jr z, .asm_daa9
- call Func_f533
- ld a, [wd49c]
- and a
- jr z, .asm_daa9
- ld a, $2
- ld [wd49c], a
- ld [wd4aa], a
- call FillBottomMessageBufferWithBlackTile
- call Func_30db
- ld hl, wd5dc
- ld de, ShootAgainText
- call LoadTextHeader
- ret
-
-.asm_daa9
- xor a
- ld [wd49c], a
- ld hl, wScreenState
- inc [hl]
- ret
-
-GameScreenFunction_EndBall: ; 0xdab2
- xor a
- ld [wd803], a
- ld a, [wGameOver]
- and a
- jp nz, TransitionToHighScoresScreen
- ld a, [wd495]
- and a
- jr nz, .asm_dae6
- ld a, [wd496]
- and a
- jr nz, .asm_db28
- call Func_cb5
- ld a, [wd849]
- and a
- call z, Func_e5d
- call Func_576
- ld hl, hSTAT
- res 6, [hl]
- ld hl, rIE
- res 1, [hl]
- ld a, $1
- ld [wScreenState], a
- ret
-
-.asm_dae6
- ld de, $0000
- call PlaySong
- ld bc, $0004
- call AdvanceFrames
- call Func_cb5
- ld a, [wd849]
- and a
- call nz, Func_e5d
- call Func_576
- ld hl, hSTAT
- res 6, [hl]
- ld hl, rIE
- res 1, [hl]
- ld a, [wCurrentStage]
- ld [wd4ad], a
- ld a, [wStageCollisionState]
- ld [wd4b0], a
- ld a, [wd497]
- ld [wCurrentStage], a
- xor a
- ld [wd496], a
- ld [wd495], a
- ld a, $0
- ld [wScreenState], a
- ret
-
-.asm_db28
- ld de, $0000
- call PlaySong
- ld bc, $0004
- call AdvanceFrames
- call Func_cb5
- ld a, [wd849]
- and a
- call nz, Func_e5d
- call Func_576
- ld hl, hSTAT
- res 6, [hl]
- ld hl, rIE
- res 1, [hl]
- ld a, [wd4ad]
- ld [wCurrentStage], a
- ld a, [wd4b0]
- ld [wStageCollisionState], a
- ld a, $1
- ld [wScreenState], a
- ret
-
-TransitionToHighScoresScreen: ; 0xdb5d
- xor a
- ld [wGameOver], a
- ld de, $0000
- call PlaySong
- ld bc, $0004
- call AdvanceFrames
- call Func_cb5
- call Func_576
- ld hl, hSTAT
- res 6, [hl]
- ld hl, rIE
- res 1, [hl]
- xor a
- ld [wd4aa], a
- ld a, [wCurrentStage]
- ld c, a
- ld b, $0
- ld hl, HighScoresStageMapping
- add hl, bc
- ld a, [hl]
- ld [wHighScoresStage], a
- ld a, SCREEN_HIGH_SCORES
- ld [wCurrentScreen], a
- xor a
- ld [wScreenState], a
- ret
-
-HighScoresStageMapping: ; 0xdb99
-; Determines which stage the high scores screen will start in,
-; based on the map the player ended in.
-; See wHighScoresStage for more info.
- db $00 ; STAGE_RED_FIELD_TOP
- db $00 ; STAGE_RED_FIELD_BOTTOM
- db $00
- db $00
- db $01 ; STAGE_BLUE_FIELD_TOP
- db $01 ; STAGE_BLUE_FIELD_BOTTOM
- db $00 ; STAGE_GENGAR_BONUS
- db $00 ; STAGE_GENGAR_BONUS
- db $00 ; STAGE_MEWTWO_BONUS
- db $00 ; STAGE_MEWTWO_BONUS
- db $00 ; STAGE_MEOWTH_BONUS
- db $00 ; STAGE_MEOWTH_BONUS
- db $00 ; STAGE_DIGLETT_BONUS
- db $00 ; STAGE_DIGLETT_BONUS
- db $00 ; STAGE_SEEL_BONUS
- db $00 ; STAGE_SEEL_BONUS
-
-Func_dba9: ; 0xdba9
- ld a, $85
- ld [wBottomMessageBuffer + $44], a
- ld a, [wd49d]
- xor $3
- inc a
- add $86
- ld [wBottomMessageBuffer + $45], a
- ret
-
Start20SecondSaverTimer: ; 0xdbba
ld a, $1
ld [wBallSaverIconOn], a
@@ -2104,40 +1741,7 @@ RestoreBallSaverAfterCatchEmMode: ; 0xdc00
callba Func_14707
ret
-HandleBallLoss: ; 0xdc49
- ld a, [wCurrentStage]
- rst JumpTable ; calls JumpToFuncInTable
-CallTable_dc4d: ; 0xdc4d
- ; STAGE_RED_FIELD_TOP
- dw RedField_HandleBallLoss
- ; STAGE_RED_FIELD_BOTTOM
- dw RedField_HandleBallLoss
- dw Func_de4e
- dw Func_de4e
- ; STAGE_BLUE_FIELD_TOP
- dw BlueField_HandleBallLoss
- ; STAGE_BLUE_FIELD_TOP
- dw BlueField_HandleBallLoss
- ; STAGE_GENGAR_BONUS
- dw Func_df1a
- ; STAGE_GENGAR_BONUS
- dw Func_df1a
- ; STAGE_MEWTWO_BONUS
- dw Func_df7e
- ; STAGE_MEWTWO_BONUS
- dw Func_df7e
- ; STAGE_MEOWTH_BONUS
- dw Func_dfe2
- ; STAGE_MEOWTH_BONUS
- dw Func_dfe2
- ; STAGE_DIGLETT_BONUS
- dw Func_e056
- ; STAGE_DIGLETT_BONUS
- dw Func_e056
- ; STAGE_SEEL_BONUS
- dw Func_e08b
- ; STAGE_SEEL_BONUS
- dw Func_e08b
+INCLUDE "engine/pinball_game/ball_loss/ball_loss.asm"
Func_dc6d: ; 0xdc6d
push de
@@ -2285,1218 +1889,14 @@ Func_dd62: ; 0xdd62
call LoadOrCopyVRAMData
ret
-RedField_HandleBallLoss: ; 0xdd76
- ld a, [wBallSaverTimerFrames]
- ld hl, wBallSaverTimerSeconds
- or [hl]
- jr z, .rip
- ld a, [wNumTimesBallSavedTextWillDisplay]
- bit 7, a
- jr nz, .skip_save_text
- dec a
- ld [wNumTimesBallSavedTextWillDisplay], a
- push af
- ld de, BallSavedText
- call Func_dc6d
- pop af
- jr nz, .skip_save_text
- ld a, $1
- ld [wBallSaverTimerFrames], a
- ld [wBallSaverTimerSeconds], a
-.skip_save_text
- lb de, $15, $02
- call PlaySoundEffect
- ret
-
-.rip
- ld de, $0000
- call PlaySong
- ld bc, $001e
- call AdvanceFrames
- lb de, $25, $24
- call PlaySoundEffect
- call Start20SecondSaverTimer
- ld a, $1
- ld [wd4c9], a
- xor a
- ld [wd4de], a
- ld [wd4df], a
- call Func_ddfd
- ld a, [wd49b]
- and a
- jr z, .asm_dddd
- dec a
- ld [wd49b], a
- ld a, $1
- ld [wd49c], a
- ld de, EndOfBallBonusText
- call Func_dc6d
- ret
-
-.asm_dddd
- ld a, [wd49d]
- ld hl, wd49e
- cp [hl]
- jr z, .asm_ddf1
- inc a
- ld [wd49d], a
- ld de, EndOfBallBonusText
- call Func_dc6d
- ret
-
-.asm_ddf1
- ld de, EndOfBallBonusText
- call Func_dc6d
- ld a, $1
- ld [wGameOver], a
- ret
-
-Func_ddfd: ; 0xddfd
- ld a, [wInSpecialMode]
- and a
- ret z
- ld a, [wSpecialMode]
- and a
- jr nz, .asm_de14
- callba Func_10157
- jr .asm_de40
-
-.asm_de14
- cp $1
- jr nz, .asm_de2d
- xor a
- ld [wd604], a
- ld a, $1e
- ld [wd607], a
- callba Func_10ac8
- jr .asm_de40
-
-.asm_de2d
- xor a
- ld [wd604], a
- ld a, $1e
- ld [wd607], a
- callba Func_3022b
-.asm_de40
- ld a, [wd7ad]
- ld c, a
- ld a, [wStageCollisionState]
- and $1
- or c
- ld [wStageCollisionState], a
- ret
-
-Func_de4e: ; 0xde4e
- ret
-
-BlueField_HandleBallLoss: ; 0xde4f
- ld a, [wBallSaverTimerFrames]
- ld hl, wBallSaverTimerSeconds
- or [hl]
- jr z, .rip
- ld a, [wNumTimesBallSavedTextWillDisplay]
- bit 7, a
- jr nz, .skip_save_text
- dec a
- ld [wNumTimesBallSavedTextWillDisplay], a
- push af
- ld de, BallSavedText
- call Func_dc6d
- pop af
- jr nz, .skip_save_text
- ld a, $1
- ld [wBallSaverTimerFrames], a
- ld [wBallSaverTimerSeconds], a
-.skip_save_text
- lb de, $15, $02
- call PlaySoundEffect
- ret
-
-.rip
- ld de, $0000
- call PlaySong
- ld bc, $001e
- call AdvanceFrames
- lb de, $25, $24
- call PlaySoundEffect
- call Start20SecondSaverTimer
- ld a, $1
- ld [wd4c9], a
- xor a
- ld [wd4de], a
- ld [wd4df], a
- call Func_ded6
- ld a, [wd49b]
- and a
- jr z, .asm_deb6
- dec a
- ld [wd49b], a
- ld a, $1
- ld [wd49c], a
- ld de, EndOfBallBonusText
- call Func_dc6d
- ret
-
-.asm_deb6
- ld a, [wd49d]
- ld hl, wd49e
- cp [hl]
- jr z, .asm_deca
- inc a
- ld [wd49d], a
- ld de, EndOfBallBonusText
- call Func_dc6d
- ret
-
-.asm_deca
- ld de, EndOfBallBonusText
- call Func_dc6d
- ld a, $1
- ld [wGameOver], a
- ret
-
-Func_ded6: ; 0xded6
- ld a, [wInSpecialMode]
- and a
- ret z
- ld a, [wSpecialMode]
- and a
- jr nz, .asm_deec
- callba Func_10157
- ret
-
-.asm_deec
- cp $1
- jr nz, .asm_df05
- ld a, $0
- ld [wd604], a
- ld a, $1e
- ld [wd607], a
- callba Func_10ac8
- ret
-
-.asm_df05
- ld a, $0
- ld [wd604], a
- ld a, $1e
- ld [wd607], a
- callba Func_3022b
- ret
-
-Func_df1a: ; 0xdf1a
- ld a, [wd4ad]
- ld hl, wCurrentStage
- cp [hl]
- ret z
- ld a, [wd6a8]
- and a
- jr nz, .asm_df57
- ld a, [wd6a2]
- cp $5
- jr c, .asm_df50
- xor a
- ld [wd4ae], a
- ld a, [wd6a7]
- and a
- ret nz
- ld [wd548], a
- ld [wd549], a
- ld [wBallSpin], a
- ld [wBallRotation], a
- ld hl, wBallXVelocity
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld a, $1
- ld [wd6a7], a
-.asm_df50
- lb de, $00, $02
- call PlaySoundEffect
- ret
-
-.asm_df57
- xor a
- ld [wd495], a
- ld a, $1
- ld [wd496], a
- ld a, $2
- ld [wd4c8], a
- xor a
- ld [wd7ac], a
- ld a, [wd49a]
- and a
- ret nz
- call FillBottomMessageBufferWithBlackTile
- call Func_30db
- ld hl, wd5dc
- ld de, EndGengarStageText
- call LoadTextHeader
- ret
-
-Func_df7e: ; 0xdf7e
- ld a, [wd4ad]
- ld hl, wCurrentStage
- cp [hl]
- ret z
- ld a, [wd6b3]
- and a
- jr nz, .asm_dfbb
- ld a, [wd6b1]
- cp $8
- jr c, .asm_dfb4
- xor a
- ld [wd4ae], a
- ld a, [wd6b2]
- and a
- ret nz
- ld [wd548], a
- ld [wd549], a
- ld [wBallSpin], a
- ld [wBallRotation], a
- ld hl, wBallXVelocity
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld a, $1
- ld [wd6b2], a
-.asm_dfb4
- lb de, $00, $0b
- call PlaySoundEffect
- ret
-
-.asm_dfbb
- xor a
- ld [wd495], a
- ld a, $1
- ld [wd496], a
- ld a, $2
- ld [wd4c8], a
- xor a
- ld [wd7ac], a
- ld a, [wd49a]
- and a
- ret nz
- call FillBottomMessageBufferWithBlackTile
- call Func_30db
- ld hl, wd5dc
- ld de, EndMewtwoStageText
- call LoadTextHeader
- ret
-
-Func_dfe2: ; 0xdfe2
- xor a
- ld [wd64e], a
- ld a, [wd7be]
- and a
- jr z, .asm_dff2
- ld a, [wd49a]
- and a
- jr z, .asm_e00f
-.asm_dff2
- ld a, [wMeowthStageScore]
- cp $14
- jr nc, .asm_e00f
- cp $5
- jr c, .asm_e001
- sub $4
- jr .asm_e002
-
-.asm_e001
- xor a
-.asm_e002
- ld [wMeowthStageScore], a
- callba Func_24fa3
-.asm_e00f
- ld a, [wd4ad]
- ld hl, wCurrentStage
- cp [hl]
- ret z
- ld a, [wd712]
- cp $0
- jr nz, .asm_e025
- lb de, $00, $02
- call PlaySoundEffect
- ret
-
-.asm_e025
- xor a
- ld [wd57e], a
- ld [wd57d], a
- xor a
- ld [wd495], a
- ld a, $1
- ld [wd496], a
- ld a, $2
- ld [wd4c8], a
- xor a
- ld [wd7ac], a
- ld [wd712], a
- ld a, [wd49a]
- and a
- ret nz
- call FillBottomMessageBufferWithBlackTile
- call Func_30db
- ld hl, wd5dc
- ld de, EndMeowthStageText
- call LoadTextHeader
- ret
-
-Func_e056: ; 0xe056
- ld a, [wd4ad]
- ld hl, wCurrentStage
- cp [hl]
- ret z
- lb de, $00, $0b
- call PlaySoundEffect
- xor a
- ld [wd495], a
- ld a, $1
- ld [wd496], a
- ld a, $2
- ld [wd4c8], a
- xor a
- ld [wd7ac], a
- ld a, [wd49a]
- and a
- ret nz
- call FillBottomMessageBufferWithBlackTile
- call Func_30db
- ld hl, wd5dc
- ld de, EndDiglettStageText
- call LoadTextHeader
- ret
-
-Func_e08b: ; 0xe08b
- xor a
- ld [wd64e], a
- ld a, [wd7be]
- and a
- jr z, .asm_e09b
- ld a, [wd49a]
- and a
- jr z, .asm_e0b8
-.asm_e09b
- ld a, [wd793]
- cp $14
- jr nc, .asm_e0b8
- cp $5
- jr c, .asm_e0aa
- sub $4
- jr .asm_e0ab
-
-.asm_e0aa
- xor a
-.asm_e0ab
- ld [wd793], a
- callba Func_262f4
-.asm_e0b8
- ld a, [wd4ad]
- ld hl, wCurrentStage
- cp [hl]
- ret z
- ld a, [wd794]
- cp $0
- jr nz, .asm_e0c8
- ret
-
-.asm_e0c8
- lb de, $00, $02
- call PlaySoundEffect
- xor a
- ld [wd57d], a
- ld [wd57d], a
- ld [wd495], a
- ld a, $1
- ld [wd496], a
- ld a, $2
- ld [wd4c8], a
- xor a
- ld [wd7ac], a
- ld [wd794], a
- ld a, [wd49a]
- and a
- ret nz
- call FillBottomMessageBufferWithBlackTile
- call Func_30db
- ld hl, wd5dc
- ld de, EndSeelStageText
- call LoadTextHeader
- ret
-
-HandleFlippers: ; 0xe0fe
- xor a
- ld [wFlipperCollision], a
- ld [hFlipperYCollisionAttribute], a
- ld [wFlipperXForce], a
- ld [wFlipperXForce + 1], a
- call Func_e118
- call CheckFlipperCollision
- ld a, [wFlipperCollision]
- and a
- call nz, HandleFlipperCollision
- ret
-
-Func_e118: ; 0xe118
- call PlayFlipperSoundIfPressed
- ld a, [wd7af]
- ld [wLeftFlipperAnimationState], a
- ld a, [wd7b3]
- ld [wRightFlipperAnimationState], a
- ld hl, wKeyConfigLeftFlipper
- call IsKeyPressed2
- ld hl, -$0333
- jr z, .asm_e13b
- ld a, [wd7be]
- and a
- jr nz, .asm_e13b
- ld hl, $0333
-.asm_e13b
- ld a, [wd7af]
- and a
- jr nz, .asm_e145
- bit 7, h
- jr nz, .asm_e14d
-.asm_e145
- cp $f
- jr nz, .asm_e150
- bit 7, h
- jr nz, .asm_e150
-.asm_e14d
- ld hl, $0000
-.asm_e150
- ld a, l
- ld [wd7b0], a
- ld a, h
- ld [wd7b1], a
- ld a, [wd7ae]
- ld c, a
- ld a, [wd7af]
- ld b, a
- add hl, bc
- bit 7, h
- jr nz, .asm_e16f
- ld a, h
- cp $10
- jr c, .asm_e172
- ld hl, $0f00
- jr .asm_e172
-
-.asm_e16f
- ld hl, $0000
-.asm_e172
- ld a, l
- ld [wd7ae], a
- ld a, h
- ld [wd7af], a
- ld hl, wKeyConfigRightFlipper
- call IsKeyPressed2
- ld hl, -$0333
- jr z, .asm_e18e
- ld a, [wd7be]
- and a
- jr nz, .asm_e18e
- ld hl, $0333
-.asm_e18e
- ld a, [wd7b3]
- and a
- jr nz, .asm_e198
- bit 7, h
- jr nz, .asm_e1a0
-.asm_e198
- cp $f
- jr nz, .asm_e1a3
- bit 7, h
- jr nz, .asm_e1a3
-.asm_e1a0
- ld hl, $0000
-.asm_e1a3
- ld a, l
- ld [wd7b4], a
- ld a, h
- ld [wd7b5], a
- ld a, [wd7b2]
- ld c, a
- ld a, [wd7b3]
- ld b, a
- add hl, bc
- bit 7, h
- jr nz, .asm_e1c2
- ld a, h
- cp $10
- jr c, .asm_e1c5
- ld hl, $0f00
- jr .asm_e1c5
-
-.asm_e1c2
- ld hl, $0000
-.asm_e1c5
- ld a, l
- ld [wd7b2], a
- ld a, h
- ld [wd7b3], a
- ret
-
-PlayFlipperSoundIfPressed: ; 0xe1ce
- ld a, [wd7be]
- and a
- ret nz
- ld hl, wKeyConfigLeftFlipper
- call IsKeyPressed
- jr z, .asm_e1e2
- lb de, $00, $0c
- call PlaySoundEffect
- ret
-
-.asm_e1e2
- ld hl, wKeyConfigRightFlipper
- call IsKeyPressed
- ret z
- lb de, $00, $0c
- call PlaySoundEffect
- ret
-
-CheckFlipperCollision: ; 0xe1f0
- ld a, [wBallXPos + 1]
- cp $50 ; which half of the screen is the ball in?
- jp nc, CheckRightFlipperCollision ; right half of screen
- ; fall through
-CheckLeftFlipperCollision:
- ld hl, wBallXPos
- ld c, $ba
- ld a, [hli]
- ld [$ff00+c], a
- inc c
- ld a, [hli]
- ld [$ff00+c], a
- inc c
- ld a, [hli]
- ld [$ff00+c], a
- inc c
- ld a, [hli]
- ld [$ff00+c], a
- inc c
- ld a, [wLeftFlipperAnimationState]
- ld [$ffc2], a
- ld a, [wd7af]
- ld [$ffc3], a
- call ReadFlipperCollisionAttributes
- ld a, [wFlipperCollision]
- and a
- ret z
- ld a, [wd7b0]
- ld [$ffc0], a
- ld a, [wd7b1]
- ld [$ffc1], a
- ret
-
-CheckRightFlipperCollision: ; 0xe226
-; ball is in right half of screen
- ld hl, wBallXPos
- ld c, $ba
- ld a, [hli]
- sub $1
- cpl
- ld [$ff00+c], a
- inc c
- ld a, [hli]
- sbc $a0
- cpl
- ld [$ff00+c], a
- inc c
- ld a, [hli]
- ld [$ff00+c], a
- inc c
- ld a, [hli]
- ld [$ff00+c], a
- inc c
- ld a, [wRightFlipperAnimationState]
- ld [$ffc2], a
- ld a, [wd7b3]
- ld [$ffc3], a
- call ReadFlipperCollisionAttributes
- ld a, [wFlipperCollision]
- and a
- ret z
- ; collision with flipper occurred
- ld a, [wd7b4]
- ld [$ffc0], a
- ld a, [wd7b5]
- ld [$ffc1], a
- ret
-
-ReadFlipperCollisionAttributes: ; 0xe25a
- ld a, [$ffbb] ; ball x-position high byte
- sub $2b ; check if ball is in x-position range of flippers
- ret c
- cp $30
- ret nc
- ; ball is in x-position range of flippers
- ld [$ffbb], a ; x offset of flipper horizontal range
- ld a, [$ffbd] ; ball y-position high byte
- sub $7b ; check if ball is in y-position range of flippers
- ret c
- cp $20
- ret nc
- ; ball is in potential collision with flippers
- ld [$ffbd], a ; y offset of flipper vertical range
- ld a, [$ffc2] ; flipper animation state
-.asm_e270
- push af
- ld l, $0
- ld h, a ; multiply a by 0x600
- sla a
- sla h
- sla h
- add h
- ld h, a ; hl = a * 0x600 (this is the length of the flipper collision attributes)
- ld a, [$ffbb] ; x offset of flipper horizontal range
- ld c, a
- ld b, $0
- sla c
- rl b
- sla c
- rl b
- sla c
- rl b
- sla c
- rl b
- sla c
- rl b ; bc = (x offset of flipper horizontal range) * 32
- ; Each row of the flipper collision attributes is 32 bytes long.
- add hl, bc ; hl points to the start of the row in the flipper collisoin attributes
- ld a, [$ffbd] ; y offset of flipper vertical range
- ld c, a
- ld b, $0
- add hl, bc ; hl points to the attribute byte in the flipper collision attributes
- ld d, h
- ld e, l ; de points to the attribute byte in the flipper collision attributes
- ld a, h
- cp $40
- jr nc, .secondBank
- add $40
- ld h, a
- ld a, Bank(FlipperHorizontalCollisionAttributes)
- jr .readAttributeByte
-
-.secondBank
- ld a, Bank(FlipperHorizontalCollisionAttributes2)
-.readAttributeByte
- call ReadByteFromBank
- ld b, a
- and a
- jr nz, .collision
- ; no collision
- pop af ; a = flipper animation state(?)
- ld hl, $ffc3
- cp [hl]
- ret z
- jr c, .asm_e2be
- dec a
- jr .asm_e270
-
-.asm_e2be
- inc a
- jr .asm_e270
-
-.collision
- pop af ; a = flipper animation state(?)
- ld a, b ; a = collision attribute
- ld [hFlipperYCollisionAttribute], a
- ld h, d
- ld l, e
- ld a, h
- cp $20
- jr nc, .asm_e2d3
- add $60
- ld h, a
- ld a, Bank(FlipperVerticalCollisionAttributes)
- jr .asm_e2d8
-
-.asm_e2d3
- add $20
- ld h, a
- ld a, Bank(FlipperVerticalCollisionAttributes2)
-.asm_e2d8
- call ReadByteFromBank
- ld [wFlipperXCollisionAttribute], a
- ld a, $1
- ld [wFlipperCollision], a
- ret
-
-Func_e2e4:
- ld a, c
- or b
- or l
- or h
- or e
- or d
- jr nz, .asm_e2f3
- ld a, [$ffba]
- ld e, a
- ld a, [$ffbb]
- ld d, a
- ret
-
-.asm_e2f3
- ld a, d
- xor h
- push af
- bit 7, d
- jr z, .asm_e301
- ld a, e
- cpl
- ld e, a
- ld a, d
- cpl
- ld d, a
- inc de
-.asm_e301
- bit 7, h
- jr z, .asm_e317
- ld a, c
- cpl
- ld c, a
- ld a, b
- cpl
- ld b, a
- ld a, l
- cpl
- ld l, a
- ld a, h
- cpl
- ld h, a
- inc bc
- ld a, b
- or c
- jr nz, .asm_e317
- inc hl
-.asm_e317
- push bc
- ld c, $11
- ld a, d
- or e
- jr nz, .asm_e324
- pop bc
- ld de, $7fff
- jr .asm_e36a
-
-.asm_e324
- bit 7, d
- jr nz, .asm_e32f
- sla e
- rl d
- inc c
- jr .asm_e324
-
-.asm_e32f
- ld a, c
- ld [$ff8c], a
- pop bc
- xor a
- ld [$ff8d], a
- ld [$ff8e], a
-.asm_e338
- jr c, .asm_e344
- ld a, d
- cp h
- jr nz, .asm_e342
- ld a, e
- cp l
- jr z, .asm_e344
-.asm_e342
- jr nc, .asm_e34b
-.asm_e344
- ld a, l
- sub e
- ld l, a
- ld a, h
- sbc d
- ld h, a
- scf
-.asm_e34b
- ld a, [$ff8d]
- rla
- ld [$ff8d], a
- ld a, [$ff8e]
- rla
- ld [$ff8e], a
- sla c
- rl b
- rl l
- rl h
- ld a, [$ff8c]
- dec a
- ld [$ff8c], a
- jr nz, .asm_e338
- ld a, [$ff8d]
- ld e, a
- ld a, [$ff8e]
- ld d, a
-.asm_e36a
- pop af
- bit 7, a
- ret z
- ld a, e
- sub $1
- cpl
- ld e, a
- ld a, d
- sbc $0
- cpl
- ld d, a
- ret
-
-Func_e379: ; 0xe379
- ld a, b
- xor d
- ld [$ffbe], a
- bit 7, b
- jr z, .asm_e388
- ld a, c
- cpl
- ld c, a
- ld a, b
- cpl
- ld b, a
- inc bc
-.asm_e388
- bit 7, d
- jr z, .asm_e393
- ld a, e
- cpl
- ld e, a
- ld a, d
- cpl
- ld d, a
- inc de
-.asm_e393
- push bc
- push de
- ld c, d
- call Func_e410
- pop de
- pop bc
- push hl
- push bc
- push de
- ld c, e
- call Func_e410
- pop de
- pop bc
- push hl
- push bc
- push de
- ld b, d
- call Func_e410
- pop de
- pop bc
- push hl
- ld b, e
- call Func_e410
- ld c, l
- ld l, h
- xor a
- ld h, a
- pop de
- add hl, de
- rl a
- pop de
- add hl, de
- jr nc, .asm_e3bf
- inc a
-.asm_e3bf
- ld b, l
-Data_e3c0:
- ld l, h
- ld h, a
- pop de
- add hl, de
- ld a, [$ffbe]
- bit 7, a
- ret z
- ld a, c
- sub $1
- cpl
- ld c, a
- ld a, b
- sbc $0
- cpl
- ld b, a
- ld a, l
- sbc $0
- cpl
- ld l, a
- ld a, h
- sbc $0
- cpl
- ld h, a
- ret
-
-Func_e3de:
- push bc
- push de
- ld c, d
- call Func_e410
- pop de
- pop bc
- push hl
- push bc
- push de
- ld c, e
- call Func_e410
- pop de
- pop bc
- push hl
- push bc
- push de
- ld b, d
- call Func_e410
- pop de
- pop bc
- push hl
- ld b, e
- call Func_e410
- ld c, l
- ld l, h
- xor a
- ld h, a
- pop de
- add hl, de
- rl a
- pop de
- add hl, de
- jr nc, .asm_e40a
- inc a
-.asm_e40a
- ld b, l
- ld l, h
- ld h, a
- pop de
- add hl, de
- ret
-
-Func_e410: ; 0xe410
- ld a, b
- cp c
- jr nc, .asm_e416
- ld b, c
- ld c, a
-.asm_e416
- ld h, $3e
- ld l, c
- ld e, [hl]
- inc h
- ld d, [hl]
- ld l, b
- ld a, [hl]
- dec h
- ld l, [hl]
- ld h, a
- add hl, de
- push af
- ld d, $3e
- ld a, b
- sub c
- ld e, a
- ld a, [de]
- ld c, a
- inc d
- ld a, [de]
- ld b, a
- ld a, l
- sub c
- ld l, a
- ld a, h
- sbc b
- ld h, a
- jr nc, .asm_e43c
- pop af
- ccf
- rr h
- rr l
- ret
-
-.asm_e43c
- pop af
- rr h
- rr l
- ret
-
-HandleFlipperCollision: ; 0xe442
-; This is called when the ball is colliding with either the
-; right or left flipper.
- ld a, $1
- ld [wd7e9], a
- xor a
- ld [wBallPositionPointerOffsetFromStageTopLeft], a
- ld [wBallPositionPointerOffsetFromStageTopLeft + 1], a
- ld [wCurCollisionAttribute], a
- ld [wd7f6], a
- ld [wd7f7], a
- ld a, [hFlipperYCollisionAttribute]
- sla a
- ld c, a
- ld b, $0
- ld hl, Data_e538
- add hl, bc
- ld a, [hli]
- ld c, a
- ld a, [hl]
- ld b, a
- ld a, [$ffc0]
- ld e, a
- ld a, [$ffc1]
- ld d, a
- sla e
- rl d
- sla e
- rl d ; multiplied de by 4
- call Func_e379
- ld a, b
- ld [wFlipperYForce], a
- ld a, l
- ld [wFlipperYForce + 1], a
- ld a, [wBallXPos + 1]
- cp $50 ; which flipper did the ball hit?
- ld a, [wFlipperXCollisionAttribute]
- jr c, .asm_e48b
- cpl ; invert the x collision attribute
- inc a
-.asm_e48b
- ld [wCollisionForceAngle], a
- ld a, $1
- ld [wd7eb], a
- ld a, [wFlipperYForce + 1]
- bit 7, a
- ret z
- xor a
- ld [wFlipperYForce], a
- ld [wFlipperYForce + 1], a
- ret
-
-DrawFlippers: ; 0xe4a1
- ld a, [wCurrentStage]
- and a
- ret z
- ld hl, FlippersOAMPixelOffsetData
- ld a, [hSCX]
- ld d, a
- ld a, [hSCY]
- ld e, a
- ld a, [hli]
- sub d
- ld b, a
- ld a, [hli]
- sub e
- ld c, a
- push hl
- ld hl, LeftFlipperOAMIds
- ld a, [wd7af]
- ld e, a
- ld d, $0
- add hl, de
- ld a, [hl]
- cp $b
- jr nz, .asm_e4d6
- ld a, [hGameBoyColorFlag]
- and a
- jr nz, .asm_e4d4
- ld a, [wd7be]
- and a
- jr z, .asm_e4d4
- ld a, $18
- jr .asm_e4d6
-
-.asm_e4d4
- ld a, $b
-.asm_e4d6
- call LoadOAMData
- pop hl
- ld a, [hSCX]
- ld d, a
- ld a, [hSCY]
- ld e, a
- ld a, [hli]
- sub d
- ld b, a
- ld a, [hli]
- sub e
- ld c, a
- ld hl, RightFlipperOAMIds
- ld a, [wd7b3]
- ld e, a
- ld d, $0
- add hl, de
- ld a, [hl]
- cp $8
- jr nz, .asm_e506
- ld a, [hGameBoyColorFlag]
- and a
- jr nz, .asm_e504
- ld a, [wd7be]
- and a
- jr z, .asm_e504
- ld a, $17
- jr .asm_e506
-
-.asm_e504
- ld a, $8
-.asm_e506
- call LoadOAMData
- ret
-
-FlippersOAMPixelOffsetData:
-; flipper oam pixel offsets
- dw $7b38 ; left flipper
- dw $7b68 ; right flipper
-
-LeftFlipperOAMIds:
-; TODO: Don't know how exactly these are used, but it is used by the animation
-; when the flipper is activated and rotates upward to hit the pinball.
- db $0b, $0b, $0b, $0b, $0b, $0b, $0b
- db $0c, $0c, $0c, $0c, $0c, $0c, $0c
- db $0d, $0d, $0d, $0d, $0d, $0d, $0d
-
-RightFlipperOAMIds:
- db $08, $08, $08, $08, $08, $08, $08
- db $09, $09, $09, $09, $09, $09, $09
- db $0A, $0A, $0A, $0A, $0A, $0A, $0A
-
-Data_e538: ; 0xe538
- dw $0000
- dw $000C
- dw $001C
- dw $0030
- dw $0038
- dw $0048
- dw $005C
- dw $006C
- dw $0070
- dw $0080
- dw $0094
- dw $00A4
- dw $00B4
- dw $00C4
- dw $00D4
- dw $00E4
- dw $00F8
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
- dw $00FC
+INCLUDE "engine/pinball_game/ball_loss/ball_loss_red_field.asm"
+INCLUDE "engine/pinball_game/ball_loss/ball_loss_blue_field.asm"
+INCLUDE "engine/pinball_game/ball_loss/ball_loss_gengar_bonus.asm"
+INCLUDE "engine/pinball_game/ball_loss/ball_loss_mewtwo_bonus.asm"
+INCLUDE "engine/pinball_game/ball_loss/ball_loss_meowth_bonus.asm"
+INCLUDE "engine/pinball_game/ball_loss/ball_loss_diglett_bonus.asm"
+INCLUDE "engine/pinball_game/ball_loss/ball_loss_seel_bonus.asm"
+INCLUDE "engine/pinball_game/flippers.asm"
LoadStageCollisionAttributes: ; 0xe578
ld a, [wCurrentStage]