Skip to navigation

Revs on the BBC Micro

Drawing the track: DrawSegmentEdge (Part 1 of 7)

Name: DrawSegmentEdge (Part 1 of 7) [Show more] Type: Subroutine Category: Drawing the track Summary: Draw a single segment's edge as part of a whole track verge edge Deep dive: Drawing the track verges
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawVergeEdge calls DrawSegmentEdge

This part of the routine checks whether the edge is on-screen, off-screen or partially on-screen, and stores the yaw and pitch angles of the edge in W and RR respectively.
Arguments: A Index into the vergePixelMask table for the pixel bytes that make up the colours of this edge in this segment X Index in the verge buffer of the track segment list entry for the verge, pointing to either the inner edge or outer edge of the verge mark, depending on the verge table we are drawing (so we can use this for fetching yaw angles from the track segment list for the verge) Y Index in the verge buffer of the track segment list entry for the verge, for the inner edge of the verge mark (so we can use this for fetching pitch angles from the track segment list for the verge) C flag Flag to control whether we draw the edge, or just set up variables for the next call: * Clear = draw this edge * Set = do not draw this edge, but do set up the variables to pass to the next call M Yaw angle from the previous call to DrawSegmentEdge N Pitch angle from the previous call to DrawSegmentEdge prevYawIndex Same as X for the first call, or the yaw angle index of the previous call (i.e. the previous segment) if this is not the first call
Returns: X X is unchanged Y Y is unchanged M Set to 128 + edge's yaw angle * 4, to carry through to the next call to DrawSegmentEdge N Set to the edge's pitch angle to carry through to the next call to DrawSegmentEdge
.DrawSegmentEdge PHP \ Store the C flag on the stack so we can retrieve it \ later STA pixelMaskIndex \ Store the index into the vergePixelMask table in \ pixelMaskIndex so we can use it later LDA #0 \ Set vergeOnScreenEdge = 0 to denote that the edge is STA vergeOnScreenEdge \ fully on-screen or fully off-screen (we update this \ below if it turns out not to be the case) LDA yVergeRight,Y \ Set A to the pitch angle - 1 of the verge edge we are SEC \ drawing SBC #1 CMP #78 \ If A >= 78, jump to dver2 with the C flag set to BCS dver2 \ indicate that this verge edge is off-screen LDA xVergeRightHi,X \ Set A to the high byte of the yaw angle of the verge \ edge we are drawing BPL dver1 \ If A is positive, jump to dver1 to skip the following EOR #&FF \ Set A = ~A \ = -A - 1 \ = |A| - 1 \ \ So A is now positive is approximately |A| .dver1 CMP #20 \ If A >= 20, set the C flag, otherwise clear the C flag \ \ Because the field of view is 20 degrees, the C flag is \ now set if the verge edge is off-screen, or clear if \ it is on-screen .dver2 ROR GG \ Rotate the C flag into bit 7 of RR, so bit 7 is set if \ the edge is off-screen, or clear if it is on-screen \ \ If this is not the first call to DrawSegmentEdge, then \ bit 6 will now contain the on-screen/off-screen bit \ for the previous segment's verge edge LDA xVergeRightHi,X \ Set (W A) to the yaw angle of the verge edge we are STA W \ drawing LDA xVergeRightLo,X ASL A \ Set (W A) = (W A) * 4 ROL W \ ASL A \ So W is the high byte of the yaw angle * 4 ROL W LDA W \ Set W = W + 128 CLC \ ADC #128 \ So W contains 128 + yaw angle * 4 (if we drop the low STA W \ byte, which is the fractional part) \ \ Adding 128 moves the angle range from -128 to +128, to \ 0 to 255, so when we calculate the difference between \ the yaw angles for two segments by subtracting them \ below, the C flag will be set correctly LDA yVergeRight,Y \ Set RR to the pitch angle of the verge edge we are STA RR \ drawing STX thisYawIndex \ Store the index of the yaw angle in the track segment \ list for this verge in thisYawIndex so we can use it \ later STY thisPitchIndex \ Store the index of the pitch angle in the track \ segment list for this verge in thisPitchIndex so we \ can use it later PLP \ Retrieve the C flag that we passed to the routine and \ stored on the stack earlier BCS dver8 \ If the C flag is set then we don't draw this edge, so \ jump to dver28 via dver8 to clean up and return from \ the subroutine BIT GG \ If bit 6 of GG is clear, then the previous segment's BVC dver3 \ verge edge from the last call to DrawSegmentEdge was \ on-screen, so jump to dver3 \ If we get here then previous segment's verge edge from \ the last call to DrawSegmentEdge was off-screen BMI dver8 \ If bit 7 of GG is set, then this segment's verge edge, \ which we are now drawing, is also off-screen, so jump \ to dver28 via dver8 to clean up and return from the \ subroutine \ If we get here then the previous verge edge was \ off-screen but this one is on-screen \ We now swap the values of M and W, and the values of \ N and RR, which sets W and RR to the yaw and pitch \ angles of the previous edge LDX M \ Set X = M and Y = N LDY N LDA W \ Set M = W STA M LDA RR \ Set N = RR STA N STX W \ Set W = X \ = M STY RR \ Set RR = Y \ = N DEC vergeOnScreenEdge \ Set vergeOnScreenEdge = &FF (as it was set to 0 above) \ to flag that this edge is partially off-screen and \ that we have swapped the angles over \ By this point, we have the following: \ \ * W = the yaw angle of the edge to draw \ \ * RR = the pitch angle of the edge to draw \ \ * M = the yaw angle of the previous edge \ \ * N = the pitch angle of the previous edge \ \ We only get to this point if this is not the first \ call to DrawSegmentEdge for this verge edge, so we \ know that M and N are defined