Skip to navigation

Revs on the BBC Micro

Drawing the track: DrawSegmentEdge (Part 2 of 7)

Name: DrawSegmentEdge (Part 2 of 7) [Show more] Type: Subroutine Category: Drawing the track Summary: Set up the edge's gradient Deep dive: Drawing the track verges
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

This part calculates the edge's gradient in terms of the change in yaw and pitch angles, and stores them in SS and TT, with SS containing the yaw delta, and TT containing the pitch delta.
.dver3 LDA RR \ Set A = RR - N SEC SBC N STA WW \ Set WW = A \ \ So WW contains the current edge's pitch angle minus \ the previous edge's pitch angle, so: \ \ * WW is positive if the current pitch angle is \ greater than the previous pitch angle, so the \ current edge is higher up the screen, so the edge \ is moving up the screen \ \ * WW is negative if the current pitch angle is \ less than the previous pitch angle, so the \ current edge is lower down the screen, so the edge \ is moving down the screen BPL dver4 \ If A is positive, jump to dver4 LDA #0 \ Set A = -WW SEC \ = -A SBC WW \ \ So A is now positive, i.e. A = |RR - N| .dver4 STA TT \ Set TT = A \ = |RR - N| \ \ So TT contains the difference in pitch angle between \ the previous edge and the current edge, so let's call \ it dPitch: \ \ TT = |dPitch| LDA GG \ If bits 6 and 7 of GG are clear, then both this and AND #%11000000 \ the previous segment's verge edges were on-screen, so BEQ dver9 \ jump to dver9 to calculate the difference in yaw \ angles in SS \ If we get here then one of the previous segment's \ verge edges were off-screen, so we need to interpolate \ the angles to calculate where the edge meets the \ screen edge LDY thisYawIndex \ Set Y to the index of the yaw angle in the track \ segment list for this verge LDX prevYawIndex \ Set X to the index of the yaw angle in the track \ segment list for the segment from the previous call LDA xVergeRightLo,Y \ Set (VV T) to the difference in yaw angle between the SEC \ current segment and the previous segment, starting SBC xVergeRightLo,X \ with the low bytes STA T LDA xVergeRightHi,Y \ And then the high bytes SBC xVergeRightHi,X STA VV \ This also sets the sign of VV as follows: \ \ * VV is positive if the previous yaw angle is less \ than the current yaw angle, so the edge is moving \ from left to right \ \ * VV is negative if the previous yaw angle is \ greater than the current yaw angle, so the edge is \ moving from right to left JSR Absolute16Bit \ Set (A T) = |A T| \ \ So (A T) contains the difference in yaw angle between \ the previous edge and the current edge, so let's call \ it dYaw: \ \ (A T) = |dYaw| \ We now scale (A T) and TT, scaling (A T) up while \ scaling TT down, up to a maximum of two shifts up and \ down, as follows: \ \ * If |dYaw| >= 64, |dPitch| / 4 \ \ * If |dYaw| >= 32, |dYaw| * 2, |dPitch| / 2 \ \ * If |dYaw| < 16, |dYaw| * 4 \ \ This scales |dYaw| to be as large as possible while \ simultaneously making |dPitch| as small as possible CMP #64 \ If A >= 64, jump to dver5 to divide TT by 4 BCS dver5 ASL T \ Set (A T) = (A T) * 2 ROL A \ = |dYaw| * 2 CMP #64 \ If A >= 64, jump to dver6 to divide TT by 2 BCS dver6 ASL T \ Set (A T) = (A T) * 2 ROL A \ = |dYaw| * 4 BPL dver7 \ Jump to dver7 (this BPL is effectively a JMP as bit 7 \ of A will never be set, as the maximum value of A \ before the last ROR was 63, and 63 << 1 = 126, which \ has bit 7 clear) .dver5 LSR TT \ Set TT = TT / 2 \ = |dPitch| / 2 .dver6 LSR TT \ Set TT = TT / 2 \ = |dPitch| / 2 .dver7 STA SS \ Set SS = A \ = scaled |dYaw| LDA VV \ If vergeOnScreenEdge = &FF, then this sets VV to ~VV, EOR vergeOnScreenEdge \ which flips bit 7 (which we will use later) STA VV LDA SS \ Set A = SS JMP dver10 \ Jump to dver10 to finish setting up SS and TT .dver8 JMP dver28 \ Jump to dver28 (this is used as a way for branch \ instructions to jump to dver28, when it is too far \ for a branch instruction to reach .dver9 \ If we get here then both the previous and current \ verge edges are on-screen, so we need to set SS to the \ difference in yaw angle between the previous and \ current edges \ \ Note that we added 128 to each yaw angle to convert \ them in the range 0 to 255 (rather than -128 to +127) \ so the subtraction will set the C flag correctly LDA M \ Set A = M - W SEC \ SBC W \ So A contains the difference in yaw angle between the \ previous edge and the current edge, so let's call it \ dYaw ROR VV \ Rotate the C flag into bit 7 of VV, so bit 7 is set if \ M >= W, or clear if M < W BMI dver10 \ If A is negative, jump to dver10 to finish setting up \ SS and TT EOR #&FF \ Negate A using two's complement, so A is negative, CLC \ i.e. A = -|A| ADC #1 \ We now fall through into dver10 to set SS to A, which \ contains -|M - W|, or -|dYaw| .dver10 STA SS \ Set SS = A BNE dver11 \ If A is non-zero, jump to dver11 ORA TT \ A is zero, so this sets A to TT BEQ dver8 \ If A is zero (which means both SS and TT are zero), \ jump to dver28 via dver8 to clean up and return from \ the subroutine \ By this point, we have the following: \ \ * SS = the scaled yaw delta along the edge to draw \ (scaled to be as large as possible) \ \ * TT = the scaled pitch delta along the edge to draw \ (scaled to be as small as possible) \ \ * VV = the left-right direction of the edge \ \ * Positive = left to right \ \ * Negative = right to left \ \ * WW = the up-down direction of the edge \ \ * Positive = line is heading up the screen \ \ * Negative = line is heading down the screen \ \ So SS and TT are set to the gradient of the edge that \ we are drawing, and WW and VV are set to the direction \ of the edge