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