Skip to navigation

Revs on the BBC Micro

Track geometry: GetVergeAndMarkers (Part 2 of 4)

Name: GetVergeAndMarkers (Part 2 of 4) [Show more] Type: Subroutine Category: Track geometry Summary: Calculate the segment's verge width and outside verge coordinates
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
.gmar3 \ We calculate the verge width as follows: \ \ (U A) = scaleUp * 2 ^ (scaleDown - vergeScale) \ \ to determine the width of the verge marks on the side \ of the track \ \ The higher the value of (U A), the wider the verge for \ this segment \ \ The vergeScale factor is between 3 and 5, and scales \ the verge width differently for different track \ configurations, with larger values of vergeScale \ giving smaller verges \ \ This gives the following: \ \ * If both verges are black-and-white, then the \ verges are thin (vergeScale = 5), on both curved \ and straight sections \ \ * If this is a curve and at least one of the verges \ is red-and-white, or we're on a straight and both \ verges are red-and-white, then the verges are \ medium thickness (vergeScale = 4) \ \ * If this is a straight and only one of the verges \ is red-and-white, then the verges are thick \ (vergeScale = 3) LDA scaleDown \ Set Y = scaleDown - vergeScale SEC SBC vergeScale,Y TAY LDA #0 \ Set U = 0, to use as the high byte in (U A) STA U LDA scaleUp \ Set A = scaleUp \ \ So (U A) = scaleUp DEY \ Set Y = Y - 1 \ = scaleDown - vergeScale - 1 \ We now scale (U A) by 2 ^ Y, so if Y is 0 we don't \ do any scaling, if it's negative we scale down, and \ if it's positive we scale up \ \ Note that the -1 in the scale factor calculation is \ reversed by the right-shift that we apply below when \ setting bit 7 of the shifted result, so the result is \ as above, despite the extra -1 BEQ gmar6 \ If Y = 0, then there is no scaling to be done, so jump \ to gmar6 BPL gmar5 \ If Y > 0, then we need to scale up, so jump to gmar5 \ If we get here then Y < 0, so we need to scale down, \ specifically by right-shifting (U A) by |Y| places .gmar4 LSR U \ Set (U A) = (U A) >> 1 ROR A INY \ Increment the shift counter in Y BNE gmar4 \ Loop back to gmar4 to keep shifting right until we \ have shifted by |Y| places BEQ gmar6 \ Jump to gmar6 (this BEQ is effectively a JMP, as we \ just passed through a BNE) .gmar5 \ If we get here then Y > 0, so we need to scale up, \ specifically by left-shifting (U A) by Y places ASL A \ Set (U A) = (U A) << 1 ROL U DEY \ Decrement the shift counter in Y BNE gmar5 \ Loop back to gmar5 to keep shifting left until we \ have shifted by Y places .gmar6 STA T \ Set (U T) = (U A) \ \ So (U T) contains our scaled value LDA segmentDirection \ Set the C flag to bit 0 of segmentDirection, which LSR A \ will be 0 when our car is facing in the same direction \ as the segment we are checking, or 1 if it's the \ opposite direction ROR A \ Set A = A >> 1 and set bit 7 to the C flag EOR directionFacing \ If the C flag matches directionFacing, jump to gmar7 BPL gmar7 \ If we get here then this is the left verge, so we need \ to negate (U T) so the outside of the verge is to the \ left of the track, i.e. in a negative direction along \ the x-axis LDA #0 \ Negate (U T), starting with the low bytes SEC SBC T STA T LDA #0 \ And then the high bytes SBC U STA U \ So we now have our verge width result: \ \ (U T) = scaleUp * 2 ^ (scaleDown - vergeScale) \ \ where the sign of (U T) is positive for the right \ verge and negative for the left verge .gmar7 LDY segmentListPointer \ Set Y to the index of the current entry in the track \ segment list \ We now calculate the coordinates for the outside edge \ of the track verge by adding the verge width in (U T) \ to the track segment's verge coordinates, storing the \ result in the track segment list, 16 bytes after the \ corresponding track segment entry (so indexes 6 to 21 \ contain the track segment list, while indexes 22 to 37 \ contain the corresponding entries for the outside of \ the verge) LDA xVergeRightLo,Y \ Set (xVergeRightHi+16 xVergeRightLo+16) CLC \ = (xVergeRightHi xVergeRightLo) + (U T) ADC T \ STA xVergeRightLo+16,Y \ starting with the low bytes LDA xVergeRightHi,Y \ And then the high bytes ADC U STA xVergeRightHi+16,Y