# Driving model: ApplyWingBalance

```       Name: ApplyWingBalance                                        [Show more]
Type: Subroutine
Category: Driving model
Summary: Apply the effect of the wing settings
Deep dive: The core driving model
Driving on grass
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* ApplyDrivingModel calls ApplyWingBalance

This routine calculates the following:

xPlayerAccel = xPlayerAccel - scaledSpeed * xPrevVelocityHi

zPlayerAccel = zPlayerAccel
- scaledSpeed * (wingBalance * playerSpeedHi + 2048)
* abs(zVelocity)

where scaledSpeed = playerSpeedHi       if bumpyGrassHeight = 0
playerSpeedHi * 2   otherwise

and wingBalance = 60 + (rearWingSetting * 3 + frontWingSetting) / 2

.ApplyWingBalance

LDA xPrevVelocityHi    \ Set A = xPrevVelocityHi

JSR Absolute8Bit       \ Set A = |A|
\       = |xPrevVelocityHi|

STA U                  \ Set U = A
\       = |xPrevVelocityHi|

CMP playerSpeedHi      \ If A >= playerSpeedHi, jump to bala1
BCS bala1

LDA playerSpeedHi      \ Set A = playerSpeedHi, so A has a minimum value of
\ playerSpeedHi

.bala1

LDY bumpyGrassHeight   \ If bumpyGrassHeight = 0, jump to bala2 to skip the
BEQ bala2              \ following

ASL A                  \ Set A = A * 2
\         playerSpeedHi * 2

.bala2

STA W                  \ Set W = A
\       = playerSpeedHi       if bumpyGrassHeight = 0
\         playerSpeedHi * 2   otherwise
\
\ Let's call this value scaledSpeed

JSR Multiply8x8        \ Set (A T) = A * U
\           = scaledSpeed * |xPrevVelocityHi|

STA U                  \ Set (U T) = (A T)
\           = scaledSpeed * |xPrevVelocityHi|

LDY #6                 \ Set Y = 6, so the call to SubtractCoords uses
\ xPlayerAccel

LDA xPrevVelocityHi    \ Set A = xPrevVelocityHi so the call to SubtractCoords
\ sets the sign to abs(xPrevVelocity)

JSR SubtractCoords     \ Set:
\
\   variableY = variableY - (U T) * abs(A)
\
\ so that's:
\
\   xPlayerAccel = xPlayerAccel
\                  - scaledSpeed * |xPrevVelocityHi|
\                                * abs(xPrevVelocity)
\
\       = xPlayerAccel - scaledSpeed * xPrevVelocityHi

LDA playerSpeedHi      \ Set U = playerSpeedHi
STA U

LDA wingBalance        \ Set A = wingBalance, which is calculated as:
\
\   60 + (rearWingSetting * 3 + frontWingSetting) / 2

JSR Multiply8x8        \ Set (A T) = A * U
\           = wingBalance * playerSpeedHi

CLC                    \ Set V = A + 8
STA V                  \ so (V T) = (A T) + (8 0)
\          = wingBalance * playerSpeedHi + 2048

LDA W                  \ Set U = W
STA U                  \       = scaledSpeed

JSR Multiply8x16       \ Set:
\
\   (U T) = U * (V T)
\         =   scaledSpeed
\           * (wingBalance * playerSpeedHi + 2048)

LDY #7                 \ Set Y = 6, so the call to SubtractCoords uses
\ zPlayerAccel

LDA zVelocityHi        \ Set A = zVelocityHi so the call to SubtractCoords sets
\ the sign to abs(zVelocity)

JSR SubtractCoords     \ Set:
\
\   variableY = variableY - (U T) * abs(A)
\
\ so that's:
\
\   zPlayerAccel = zPlayerAccel - scaledSpeed
\                 * (wingBalance * playerSpeedHi + 2048)
\                 * abs(zVelocity)

RTS                    \ Return from the subroutine
```