Aviator on the BBC Micro

Flight model: ApplyTurnAndThrust (Part 2 of 2)

```       Name: ApplyTurnAndThrust (Part 2 of 2)                        [Show more]
Type: Subroutine
Category: Flight model
Summary: Calculate the (xLinear, yLinear, zLinear) vector
Context: See this subroutine in context in the source code
References: No direct references to this subroutine in this source file

This part of the routine calculates the following.

If zVelocityPHi >= 48 (so forward speed >= 500 mph), we calculate:

[ xLinear ]   [       0      ]   [   xLiftDragSc   ]
[ yLinear ] = [ yFlapsLiftSc ] - [   yLiftDragSc   ]
[ zLinear ]   [       0      ]   [ (&EA zLinearLo) ]

If zVelocityPHi < 48 (so forward speed < 500 mph), we calculate:

[ xLinear ]   [       0      ]   [ xLiftDragSc ]   [    0    ]
[ yLinear ] = [ yFlapsLiftSc ] - [ yLiftDragSc ] + [    0    ]
[ zLinear ]   [       0      ]   [ zLiftDragSc ]   [ zEngine ]

where zEngine is 0 if the engine is off, or the following if the engine is on:

zEngine = max(0, thrustScaled - (max(0, zVelocityP) / 16))
* airDensity / 512

and:

airDensity = ~yPlaneHi * 2

and thrustScaled is the thrust in (thrustHi thrustLo), but:

* Doubled if thrust >= 1024

* Doubled if zVelocity is in the range 512 to 1023

It also calls the RetractFlapsIfFast routine to retract the flaps if we are
going too fast.

SEC                    \ Set xLinear = -xLiftDragSc / 256
LDA #0                 \
SBC xLiftDragScHi      \ starting with the low bytes
STA xLinearLo

LDA #0                 \ And then the high bytes
SBC xLiftDragScTop
STA xLinearHi

SEC                    \ Set yLinear = (yFlapsLiftSc - yLiftDragSc) / 256
LDA yFlapsLiftScHi     \
SBC yLiftDragScHi      \ starting with the low bytes
STA yLinearLo

LDA yFlapsLiftScTop    \ And then the high bytes
SBC yLiftDragScTop
STA yLinearHi

LDA zVelocityPHi       \ Set A to the high byte of the forward airspeed from
\ the perspective of the plane

BMI turn3              \ If it is negative, jump down to turn3 to set A = 0 and
\ skip the following checks, as we only retract the
\ flaps if we are going to fast in a forward direction

PHA                    \ Store A on the stack so we can retrieve it after the
\ following call to RetractFlapsIfFast

JSR RetractFlapsIfFast \ Retract the flaps if we are going too fast

PLA                    \ Retrieve the value of A from the stack

BCC turn4

LDA #&EA               \ Set A = &EA and jump to turn10 to set zLinearHi to
BNE turn10             \ &EA and return from the subroutine (this BNE is
\ effectively a JMP as A is never zero)

.turn3

LDA #0                 \ We jump here if the value of zVelocityPHi in A is
\ negative, in which case we set A = 0, so we now have:
\
\   A = max(0, zVelocityPHi)

.turn4

LDX engineStatus       \ If engineStatus is zero, then the engine is not
BEQ turn8              \ running, so jump to turn8 to set the forward force
\ from the engine to zero

STA H                  \ Set X = max(0, zVelocityPHi)

STA G                  \ Set G = max(0, zVelocityPHi)

LDA zVelocityPLo       \ Set A to the low byte of the forward airspeed

LDX #3                 \ Set X as a shift counter in the following loop, so we
\ shift right by 4 places

.turn5

LSR G                  \ Set (G A) = (G A) >> 1
ROR A

DEX                    \ Decrement the shift counter

BPL turn5              \ Loop back until we have shifted right by X + 1 places,
\ so:
\
\   (G A) = (G A) >> 4
\         = max(0, zVelocityP) / 16

STA W                  \ Set (G W) = (G A)
\           = max(0, zVelocityP) / 16

LDY thrustHi           \ Set Y to the high byte of the current thrust

STY R                  \ Set (R A) = (thrustHi thrustLo)
LDA thrustLo           \           = thrust

LDX L                  \ Fetch the current value of onGround

BEQ turn7              \ If onGround is zero then we are not on the ground, so

CPY #4                 \ If thrustHi < 4, jump to turn6 to skip the following
BCC turn6              \ two instructions

ASL A                  \ Set (R A) = (R A) << 1
ROL R                  \
\ so we double the value of (R A) if the thrust is >=
\ (4 0), i.e. >= 1024

.turn6

LDY H                  \ If max(0, zVelocityPHi) >= 4, jump to turn7 to skip
CPY #4                 \ the following
BCS turn7

CPY #1                 \ If max(0, zVelocityPHi) < 1, jump to turn7 to skip
BCC turn7              \ the following

ASL A                  \ Set (R A) = (R A) << 1
ROL R                  \
\ so we double the value of (R A) again if zVelocityPHi
\ is 2 or 3, which means zVelocity is in the range (2 0)
\ to (3 255), or 512 to 1023

\ By now we have set (R A) to the thrust, scaled up as
\ follows:
\
\   * Doubled if thrust >= 1024
\
\   * Doubled if zVelocity is in the range 512 to 1023
\
\ Let's call this thrustScaled

.turn7

SEC                    \ Set (Y X) = (R A) - (G W)
SBC W                  \           = thrustScaled - (max(0, zVelocityP) / 16)
TAX                    \
\ starting with the low bytes

LDA R                  \ And then the high bytes
SBC G
TAY

BPL turn9              \ If Y is positive, skip to turn9, otherwise keep going
\ to set (Y X) = 0, so this means:
\
\   (Y X) = max(0, thrustScaled
\                  - (max(0, zVelocityP) / 16))

.turn8

LDY #0                 \ Set (Y X) = 0
LDX #0

.turn9

JSR ScaleByAltitude    \ Set (Y X V) = (Y X) * ~yPlaneHi
\
\ so (Y X) = (Y X) * ~yPlaneHi / 256
\          = max(0, thrustScaled
\                   - (max(0, zVelocityP) / 16))
\            * ~yPlaneHi / 256
\
\ or (Y X) = 0 if the engine is off

TXA                    \ Set zLinear = (Y X) - zLiftDragSc / 256
SEC                    \
SBC zLiftDragScHi      \ starting with the low bytes
STA zLinearLo

TYA                    \ And then the high bytes, so now we have the following
SBC zLiftDragScTop     \ when the engine is on:
\
\ zLinear = max(0, thrustScaled
\                  - (max(0, zVelocityP) / 16))
\           * ~yPlaneHi / 256
\           - zLiftDragSc / 256

.turn10

STA zLinearHi          \ Store the high byte of the result in zLinearHi

RTS                    \ Return from the subroutine
```