# Flight model: ApplyAerodynamics (Part 1 of 3)

```       Name: ApplyAerodynamics (Part 1 of 3)                         [Show more]
Type: Subroutine
Category: Flight model
Summary: Set up various variables to use in the aerodynamics calculations
Deep dive: The flight model
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* ApplyFlightModel (Part 2 of 7) calls ApplyAerodynamics

This part does the following:

* Set a number of variables that are used by the calculations in part 3:

xLiftDrag = xVelocityP * 2

yLiftDrag = yVelocityP * 2

zLiftDrag = zVelocityP * 2

(J I) = |yVelocityP| * 4

(SS RR) = max(|velocityP|) * 2 * ~yPlaneHi / 256

Arguments:

L                    The current value of onGround:

* 0 = we are not on the ground

* 1 = we are on the ground

.ApplyAerodynamics

\ We start by finding the maximum velocity from the
\ perspective of the plane, across all three axes
\
\ We do this by finding the maximum of |xVelocityP|,
\ |yVelocityP| and |zVelocityP|

LDA #0                 \ Set (SS RR) = 0, so we can use it to capture the
STA RR                 \ maximum value of |xVelocityP|, |yVelocityP| and
STA SS                 \ |zVelocityP|

LDX #2                 \ Set a counter in X to work through the three axes (the
\ comments below cover the iteration for the x-axis)

.aero1

LDA xVelocityPLo,X     \ Set P = xVelocityPLo
STA P

ASL A                  \ Set xLiftDrag = xVelocityP << 1
STA xLiftDragLo,X      \               = xVelocityP * 2
LDA xVelocityPHi,X     \
PHA                    \ and push xVelocityPHi onto the stack
ROL A
STA xLiftDragHi,X

PLA                    \ Set A = xVelocityPHi, so we have
\
\   (A P) = (xVelocityPHi xVelocityPLo)
\         = xVelocityP

BPL aero2              \ If A is positive, then skip the following as (A P) is

LDA #0                 \ Set (A P) = -(A P)
SEC                    \
SBC P                  \ so by this point we have (A P) = |xVelocityP|
STA P
LDA #0
SBC xVelocityPHi,X

.aero2

STA Q                  \ Set (Q P) = (A P)
\           = |xVelocityP|

CPX #1                 \ If X <> 1, jump to aero3 to skip the following, so
BNE aero3              \ (J I) only gets set on the y-axis iteration

LDA P                  \ Set (A I) = (Q P)
STA I                  \           = |yVelocityP|
LDA Q

ASL I                  \ Set (A I) = (A I) << 2
ROL A                  \           = (Q P) << 2
ASL I                  \           = |yVelocityP| * 4
ROL A

STA J                  \ Set (J I) = (A I)
\           = |yVelocityP| * 4

LDA Q                  \ Set A to the high byte of (Q P), so we have
\ (A P) = |xVelocityP| once again

.aero3

\ We now compare the two 16-bit values in (A P) and
\ (SS RR), by first comparing the high bytes, and if
\ they are equal, comparing the low bytes
\
\ It then sets (SS RR) to the higher value, so this does
\ the following:
\
\   (SS RR) = max((SS RR), (Q P))
\           = max((SS RR), |xVelocityP|)
\
\ Note that at this point, (A P) and (Q P) are the same

CMP SS                 \ If A < SS, jump to aero5 to leave (SS RR) alone, as
BCC aero5              \ (SS RR) is the higher value

BNE aero4              \ If A <> SS, i.e. A > SS, jump to aero4 with A = Q, so
\ we set (SS RR) to (Q P), as (Q P) is the higher value

\ If we get here then A = SS, so now we compare the low
\ bytes

LDA P                  \ If P < RR, jump to aero5 to leave (SS RR) alone, as
CMP RR                 \ (SS RR) is the higher value
BCC aero5

LDA Q                  \ If we get here then A = SS and P >= RR, so set A = Q
\ so we set (SS RR) to (Q P), as (Q P) is the higher
\ value

.aero4

STA SS                 \ Set (SS RR) = (A P)
LDA P                  \             = max((SS RR), |xVelocityP|)
STA RR

.aero5

DEX                    \ Decrement the loop counter to move to the next axis

BPL aero1              \ Loop back until we have processed all three axes

\ So we now have the following:
\
\   xLiftDrag = xVelocityP * 2
\
\   yLiftDrag = yVelocityP * 2
\
\   zLiftDrag = zVelocityP * 2
\
\   (J I) = |yVelocityP| * 4
\
\   (SS RR) = max(0, |xVelocityP|, |yVelocityP|,
\                    |zVelocityP|)
\
\ Let's call this last one max(|velocityP|)

ASL RR                 \ Set (SS RR) = (SS RR) << 1
ROL SS                 \             = max(|velocityP|) * 2

LDY SS                 \ Set (Y X) = (SS RR)
LDX RR                 \           = max(|velocityP|) * 2

JSR ScaleByAltitude    \ Set (Y X V) = (Y X) * ~yPlaneHi
\             = max(|velocityP|) * 2 * ~yPlaneHi

STY SS                 \ Set (SS RR) = (Y X)
STX RR                 \             = max(|velocityP|) * 2 * ~yPlaneHi / 256
```