.gsec6 TAY \ Set Y = the section number * 8 that we calculated in \ part 3 STY thisSectionNumber \ Store the section number * 8 in thisSectionNumber, so \ we can retrieve it below when looping back LDX sectionListPointer \ Set X = sectionListPointer, to use as a counter in the \ two loops below \ We run the following section twice, once for the inner \ track section coordinates with X = sectionListPointer, \ and a second time for the outer track section \ coordinates with X = sectionListPointer + 40 .gsec7 STX sectionCounter \ Store the loop counter in sectionCounter LDX #&FD \ Copy the first trackSectionI coordinate for track JSR GetSectionCoord \ section Y into xCoord2, so xCoord2 is the 3D \ coordinate of the inner track at the start of the \ section (or, if this is the second loop where Y has \ been incremented by 3, xCoord2 is the 3D coordinate \ of the outer track) JSR GetObjYawAngle-2 \ Calculate xCoord2's yaw angle, from the point of view \ of the player, returning it in (JJ II) LDY sectionCounter \ Set Y to the loop counter BIT directionFacing \ If bit 7 of directionFacing is clear, then we are BPL gsec8 \ facing forwards, so jump to gsec8 TYA \ We are facing backwards, so flip Y between EOR #40 \ sectionListPointer and sectionListPointer + 40 to do TAY \ the inner and outer track sections in reverse order \ (so we always do the right track verge first, then the \ left track verge, where right and left are relative to \ the direction we are facing) .gsec8 JSR GetSectionYawAngle \ Set the following for the Y-th section, to calculate \ the difference in yaw angle between the track section \ and the player: \ \ xVergeRight = (JJ II) - playerYawAngle \ \ Also set (L K) to the distance between the track \ section and the player's car LDX sectionCounter \ If the loop counter in X >= 40, then we are dealing CPX #40 \ with the outer track section, so jump to gsec10 as we BCS gsec10 \ don't need to repeat the pitch angle calculation (the \ track is level from left to right, so the outer track \ is the same pitch angle as the inner track) LDX #&FD \ Set X = &FD so the call to GetObjPitchAngle uses \ xCoord2, which we set above to the 3D coordinate of \ the inner track at the start of the section JSR GetObjPitchAngle-2 \ Calculate xCoord2's pitch angle, from the point \ of view of the player, returning it in A and LL LDX sectionCounter \ Set X to the loop counter, which we know is less than \ 40 at this point (and which is therefore equal to \ sectionListPointer) LDA LL \ Set A to the pitch angle that we just calculated \ for the track section STA yVergeRight,X \ Store the pitch angle in the X-th yVergeRight \ entry, for this point on the right track section STA yVergeLeft,X \ Store the same pitch angle in the X-th yVergeLeft, \ for this point on the left track section, which will \ at the same pitch angle as the track is level from \ left to right CMP horizonLine \ If A < horizonLine, then this track section is lower BCC gsec10 \ than the current horizon, so jump to gsec10 to move on \ to the outer track section, as this section will not \ be obscuring the horizon BNE gsec9 \ If A <> horizonLine, i.e. A > horizonLine, then this \ means the track section is higher than the current \ horizon line, so jump to gsec9 to set the horizon \ line to the pitch angle of this track section, as the \ section is obscuring the horizon \ If we get here, then A = horizonLine, so this section \ is at the same pitch angle as the current horizon line CPX horizonListIndex \ If X < horizonListIndex, then this section has a lower BCC gsec10 \ index than the current horizon section, so jump to \ gsec10 as horizonListIndex already contains the higher \ index, and a higher index is closer to the player, so \ we don't need to change the horizon line details .gsec9 \ If we get here then we want to update the horizon to \ the pitch angle of the track section we are updating, \ as it obscures the horizon STA horizonLine \ Set horizonLine to the pitch angle in A, so the \ horizon is set to the pitch angle of this track \ section STX horizonListIndex \ Store the index of this section in the track section \ list in horizonListIndex .gsec10 TXA \ Set A = X + 40 CLC \ = sectionListPointer + 40 ADC #40 \ \ So A now points to the outer track section coordinates \ and is ready to be put into X (and, when we look back, \ into sectionCounter) for the loop back to gcsec7 below CMP #60 \ If A >= 60, we have done both inner and outer track BCS gsec11 \ sections, so jump to gsec11 TAX \ Set X = A \ = sectionListPointer + 40 LDA thisSectionNumber \ Set Y = thisSectionNumber + 3 CLC \ ADC #3 \ So when we loop back, the offset in Y points to the TAY \ trackSectionO coordinates for the outer track section \ instead of the inner coordinates in trackSectionI (as \ the outer coordinates are 3 bytes after the inner ones \ in the track data) JMP gsec7 \ Loop back to gsec7 to process the outer track section .gsec11 \ If we get here then we have updated this entry in the \ track section list with both left and right angles, so \ we now update the list pointers LDX sectionListPointer \ Set X = sectionListPointer - 1 DEX JSR SetSectionPointers \ Update the section list pointers to move down through \ the track section list LDA #7 \ If prevHorizonIndex <= 7, then the previous call to CMP prevHorizonIndex \ GetTrackAndMarkers (on the last iteration of the main BCS gsec12 \ driving loop) had the horizon on one of the sections \ in the track section list, or the first entry in the \ track segment list (as the list starts at index 6), so \ jump to gsec12 to skip the following STA horizonLine \ If we get here then the previous iteration around the \ main loop had the horizon line on one of the track \ segments in the track segment list (but not the first \ entry in the list), so set horizonLine to 7 .gsec12 RTS \ Return from the subroutineName: GetSectionAngles (Part 3 of 3) [Show more] Type: Subroutine Category: Track geometry Summary: Calculate the yaw and pitch angles for the track section entry that we want to update Deep dive: Data structures for the track calculations The track vergesContext: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
This part of the routine sets the yaw and pitch angles for this track section in the xVergeRight/Left and yVergeRight/Left tables.
[X]
Entry point GetObjPitchAngle-2 in subroutine GetObjPitchAngle (category: 3D objects)
Use yPlayerCoord (Y = 0)
[X]
Entry point GetObjYawAngle-2 in subroutine GetObjYawAngle (Part 1 of 4) (category: 3D objects)
Use xPlayerCoord (Y = 0)
[X]
Subroutine GetSectionCoord (category: Track geometry)
Copy a three-part 16-bit coordinate from the track section data
[X]
Subroutine GetSectionYawAngle (category: Track geometry)
Calculate the difference in yaw angle between an object and the player
[X]
Subroutine SetSectionPointers (category: Track geometry)
Set the track section list pointer to a specific value and update the validity pointer accordingly
[X]
Variable directionFacing in workspace Zero page
The direction that our car is facing
[X]
Label gsec10 is local to this routine
[X]
Label gsec11 is local to this routine
[X]
Label gsec12 is local to this routine
[X]
Label gsec7 is local to this routine
[X]
Label gsec8 is local to this routine
[X]
Label gsec9 is local to this routine
[X]
Variable horizonLine in workspace Zero page
The track line number of the horizon
[X]
Variable horizonListIndex in workspace Zero page
The track section or segment that's on the horizon, given in terms of the index within the track section list (or the track segment list)
[X]
Variable prevHorizonIndex in workspace Zero page
The value of horizonListIndex from the previous call to the GetTrackAndMarkers routine
[X]
Variable sectionCounter in workspace Zero page
A counter for the track section we are processing
[X]
Variable sectionListPointer in workspace Zero page
The index of the current entry in the track section list, as we only update one entry in the list on each iteration of the main driving loop
[X]
Variable thisSectionNumber in workspace Zero page
The number * 8 of the current section number when calculating the track verges
[X]
Variable yVergeLeft (category: Track geometry)
Segment pitch angles along the left track verge in front of the player (i.e. along the up-down y-axis)
[X]
Variable yVergeRight (category: Track geometry)
Segment pitch angles along the right track verge in front of the player (i.e. along the up-down y-axis)