Aviator on the BBC Micro

```       Name: AdjustRotation                                          [Show more]
Type: Subroutine
Category: Flight model
Summary: Move the plane and adjust its rotation
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* ApplyFlightModel (Part 6 of 7) calls AdjustRotation

This routine calculates the following:

[ xPlane ]   [ xPlane ]   [ xVelocity ]
[ yPlane ] = [ yPlane ] + [ yVelocity ]
[ zPlane ]   [ zPlane ]   [ zVelocity ]

to move the plane, and the following:

[ xRotation ]   [ xRotation ]   [ dxRotation ]
[ yRotation ] = [ yRotation ] + [ dyRotation ]
[ zRotation ]   [ zRotation ]   [ dzRotation ]

to rotate the plane.

The plane is flipped around if this makes it point backwards.

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

.arot1

\ We now do the following calculation:
\
\   xPlane = xPlane + xVelocity
\
\ Looking at this in more detail, we take the 24-bit
\ xPlane coordinate and append an extra bottom byte in
\ xPlaneBot, like this:
\
\   (xPlaneTop xPlaneHi xPlaneLo xPlaneBot)
\
\ and then we add the 16-bit velocity, like this:
\
\   (xVelocityTop xVelocityHi)
\
\ The xPlaneBot byte is not used anywhere else, it's
\ just used to keep track of the fractional part of this
\ calculation
\
\ so in terms of the original xPlane coordinate, we are
\ effectively adding xVelocityTop, but keeping track of
\ the fractional tally in xPlaneBot
\
\ Fiknally, to support negative velocities, we extend
\ xVelocity with new high and top bytes, set to 0 or &FF
\ depending on the sign of xVelocity, so that's:
\
\   (0 0 xVelocityTop xVelocityHi)
\
\ for positive velocities, or:
\
\   (&FF &FF xVelocityTop xVelocityHi)
\
\ for negative velocities

LDA #0                 \ Set R = 0 to act as the high and top bytes in the

LDA xPlaneBot,X        \ Set xPlaneBot = xPlaneBot + xVelocityHi
CLC                    \
ADC xVelocityHi,X      \ so we've added the fractional parts and set the C flag
STA xPlaneBot,X        \ accordingly

LDA xVelocityTop,X     \ Set A = xVelocityTop, ready to add the xPlaneLo and
\ xVelocityTop bytes

BPL arot2              \ If A is negative, decrement R to &FF so we can use it
DEC R                  \ as the high and top bytes for the velocity

.arot2

ADC xPlaneLo,X         \ Set xPlaneLo = xPlaneLo + xVelocityTop
STA xPlaneLo,X         \
\ so now we've added the low bytes

LDA xPlaneHi,X         \ And then we do the high bytes
STA xPlaneHi,X

LDA xPlaneTop,X        \ And then the top bytes
STA xPlaneTop,X        \ so we now have the result we want:
\
\   (xPlaneTop xPlaneHi xPlaneLo xPlaneBot) +=
\                             (xVelocityTop xVelocityHi)

LDA xRotationLo,X      \ Set xRotation = xRotation + dxRotation
CLC                    \
ADC dxRotationLo,X     \ starting with the low bytes
STA xRotationLo,X

LDA xRotationHi,X      \ And then the high bytes
STA xRotationHi,X

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

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

ASL A                  \ At the end of the above loop, A = xRotationHi, so this
EOR xRotationHi        \ checks whether bit 6 and 7 of xRotationHi are the same
BPL arot4              \ and if they are, it jumps to arot4 to return from the
\ subroutine
\
\ Bits 6 and 7 of xRotationHi are the same when the
\ rotation angle is either 0 to 63 or 192 to 255 - in
\ other words, when the plane is facing forwards:
\
\   *   0 = straight ahead  (bit 6 clear, bit 7 clear)
\   *  64 = vertical up     (bit 6 set,   bit 7 clear)
\   * 128 = backwards       (bit 6 clear, bit 7 set)
\   * 192 = nosedive        (bit 6 set,   bit 7 set)
\
\ so this only runs the following if the plane is now
\ pointing backwards, in which case we set bit 7 of the
\ rotation in the y- and z-axes (which adds 128, or
\ rotates by 180 degrees), and reflect the x-axis by
\ subtracting the rotation from 128

LDX #1                 \ Set a counter in X to work through the y- and z-axes

.arot3

LDA yRotationHi,X      \ Flip the sign of yRotationHi and zRotationHi
EOR #%10000000
STA yRotationHi,X

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

BPL arot3              \ Loop back until we have processed both axes

LDA #0                 \ Set xRotation = (128 0) - xRotation, starting with the
SEC                    \ low bytes
SBC xRotationLo
STA xRotationLo

LDA #128               \ And then the high bytes
SBC xRotationHi
STA xRotationHi

.arot4

RTS                    \ Return from the subroutine
```