Skip to navigation

Revs on the BBC Micro

# Dashboard: UpdateMirrors

```       Name: UpdateMirrors                                           [Show more]
Type: Subroutine
Category: Dashboard
Summary: Update the wing mirrors to show any cars behind us
Deep dive: Wing mirrors
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* MainDrivingLoop (Part 2 of 5) calls UpdateMirrors

ORG &7B00

.UpdateMirrors

LDY positionBehind     \ Set Y to the position of the driver behind us

LDX driversInOrder,Y   \ Set X to the number of the driver behind us

LDA objectStatus,X     \ If the object status byte for the car behind us has
BMI upmi1              \ bit 7 set, then it is hidden, so jump to upmi1 to
\ clear the mirror (as V will be set to a negative
\ value, and this will never match any values from
\ mirrorSegment, as all the mirrorSegment entries are
\ positive)

\ We now calculate the size of the car to draw in the
\ mirror (in other words, the height of the block we
\ draw)
\
\ We do this by taking the scale factor for the driver
\ behind (which is the same as the size of the car) and
\ dividing by 8 to give us half the number of pixel
\ lines to draw, in T (so if T = 1, we draw a block
\ that's two pixels high, and if T = 4, we draw a block
\ that's eight pixels high)
\
\ We then calculate the upper and lower offsets within
\ the mirror segment, by taking the offset of the middle
\ row in the segment, and adding and subtracting T to
\ give us T rows either side of &B6 in TT and N
\
\ We then pass N and TT (the latter via A) into the
\ DrawCarInMirror routine

LDA objectSize,X       \ Set A = the size of the object for the driver behind

LSR A                  \ Set T = A / 8
LSR A                  \       = objectSize / 8
LSR A
STA T

CLC                    \ Set TT = &B6 + T
ADC #&B6
STA TT

LDA #&B6               \ Set N = &B6 - T
SEC
SBC T
STA N

\ Next we calculate the mirror segment that the car
\ should appear in, based on the difference in yaw angle
\ between the car (whose angle is in objYawAngleHi), and
\ the player (whose angle is in playerYawAngleHi),
\ storing the result in A
\
\ This gives us the amount of distance that the car
\ behind the player is to either side of the player, in
\ terms of yaw angle
\
\ This can then be matched with the values in the
\ mirrorSegment table to see which segment we should
\ show the car in, with larger yaw angles mapping to
\ segments towards the outside of the mirrors

LDA objYawAngleHi,X    \ Set A = objYawAngleHi for the driver behind

SEC                    \ Set A = A - playerYawAngleHi - 4
SBC playerYawAngleHi   \       = objYawAngleHi - playerYawAngleHi - 4
SEC
SBC #4

LSR A                  \ Set A = A >> 3
LSR A                  \       = A div 8
LSR A

.upmi1

STA V                  \ Set V = A

\ So by this point:
\
\  * V is negative if there is no car in the mirror (so
\    we must have jumped here from the BMI at the start
\    of the routine)
\
\  * Otherwise V is a yaw angle that potentially maps to
\    a mirror segment number

LDY #5                 \ We now loop through the six mirror segments, either
\ clearing or drawing each of them, so we set up a loop
\ counter in Y to count from 5 to 0

.upmi2

LDA V                  \ If V matches this segment's mirrorSegment value, then
CMP mirrorSegment,Y    \ we can see a car in this segment, so jump to upmi3 to
BEQ upmi3              \ set A = TT (which we calculated above to denote the
\ size of the car) and send this to mirrorContents and
\ DrawCarInMirror

\ If we get here then we can't see a car in this mirror
\ segment, so we need to clear the mirror to white

LDA mirrorContents,Y   \ If this segment's mirrorContents value is 0, then
BEQ upmi5              \ there is no car being shown in this segment, so jump
\ to upmi5 to move on to the next segment, as the
\ mirror segment is already clear

LDA #0                 \ Otherwise we need to clear this segment, so set A = 0
BEQ upmi4              \ and jump to upmi4 to send this to mirrorContents and
\ DrawCarInMirror (this BEQ is effectively a JMP as A is
\ always zero)

.upmi3

LDA TT                 \ Set A = TT to store in mirrorContents and pass to
\ DrawCarInMirror

.upmi4

STA mirrorContents,Y   \ Store A in the Y-th entry in mirrorContents, which
\ will be zero if there is no car in this mirror
\ segment, non-zero if there is

JSR DrawCarInMirror    \ Draw the car in the specified mirror segment, between
\ the upper and lower offsets in A and N

.upmi5

DEY                    \ Decrement the loop counter

BPL upmi2              \ Loop back until we have looped through 5 to 0

RTS                    \ Return from the subroutine
```