Skip to navigation

Revs on the BBC Micro

Tactics: AssistSteering

Name: AssistSteering [Show more] Type: Subroutine Category: Tactics Summary: Apply computer assisted steering (CAS) when configured Deep dive: Tactics of the non-player drivers Computer assisted steering (CAS)
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * ProcessDrivingKeys (Part 1 of 6) calls AssistSteering * ProcessDrivingKeys (Part 2 of 6) calls via AssistSteeringKeys

This routine applies computer assisted steering (CAS) to the joystick and keyboard, but only if it is enabled and we are already steering (if we are not steering, then there is no steering to assist). Jumps back to: * keys11 (joystick, CAS not enabled) * keys7 (joystick, CAS enabled, joystick is hardly steering) * keys10 (keyboard, or joystick with CAS applied)
Arguments: (U T) The amount of steering currently being applied by the steering wheel: * For joystick, contains the scaled joystick x-coordinate as a sign-magnitude number with the sign in bit 0 (1 = left, 0 = right) * For keyboard, contains a signed 16-bit number, negative if bit 0 of steeringLo is set (left), positive if bit 0 of steeringLo is clear (right) (A T) Same as (U T) V For keyboard only: * V = 1 if ";" is being pressed (steer right) * V = 2 if "L" is being pressed (steer left) * V = 0 if neither is being pressed
Returns: A A is set to steeringLo (U T) The new amount of steering to apply, adjusted to add computer assisted steering, as a sign-magnitude number
Other entry points: AssistSteeringKeys For keyboard-controlled steering
IF _SUPERIOR OR _REVSPLUS .AssistSteering JSR GetSteeringAssist \ Set X = configAssist, set the C flag to bit 7 of \ directionFacing, and update the computer assisted \ steering (CAS) indicator on the dashboard BNE asst2 \ If CAS is enabled, jump to asst2 to skip the following \ instruction and apply CAS, otherwise we jump to keys11 \ to return to the ProcessDrivingKeys routine .asst1 JMP keys11 \ Return to the ProcessDrivingKeys routine at keys11 .asst2 BCS asst1 \ If bit 7 of directionFacing is set, then our car is \ facing backwards, so jump to asst1 to jump to keys11 \ in the ProcessDrivingKeys routine, as CAS only works \ when driving forwards CMP #5 \ If A >= 5, then the joystick is currently applying BCS asst4 \ some steering, so jump to asst4 to continue applying \ CAS \ Otherwise the joystick is not being used for steering \ at the moment, so there is no steering to assist and \ we don't apply CAS JMP keys7 \ Return to the ProcessDrivingKeys routine at keys7 to \ apply no joystick steering .AssistSteeringKeys JSR GetSteeringAssist \ Set X = configAssist, set the C flag to bit 7 of \ directionFacing, and update the CAS indicator on the \ dashboard BEQ asst3 \ If CAS is not enabled, jump to asst3 to set A and jump \ to keys10 in the ProcessDrivingKeys routine BCS asst3 \ If bit 7 of directionFacing is set, then our car is \ facing backwards, so jump to asst3 to jump to keys10 \ in the ProcessDrivingKeys routine, as CAS only works \ when driving forwards LDA V \ Set A = V BNE asst5 \ If A is non-zero, then one of the steering keys is \ being held down, so jump to asst5 to continue applying \ CAS \ Otherwise the keyboard is not being used for steering \ at the moment, so there is no steering to assist and \ we don't apply CAS .asst3 JMP asst13 \ Jump to asst13 to set A to steeringLo and return to \ the ProcessDrivingKeys routine at keys210 .asst4 \ If we get here then the joystick is being used for \ steering, and (A T) contains the scaled joystick \ x-coordinate as a sign-magnitude number with the \ sign in bit 0 (1 = left, 0 = right) LDA T \ Set the C flag to the inverse of the joystick EOR #1 \ x-coordinate's sign bit from bit 0 (i.e. 0 = left, LSR A \ 1 = right) LDA #3 \ Set A to 3 (if the C flag is set, i.e. right) or 2 (if SBC #0 \ the C flag is clear, i.e. left) .asst5 \ If we get here, then either the joystick or keyboard \ is being used for steering, and we have the following: \ \ * A = 2 if we are steering left \ \ We now set X as a flag for the steering direction, so \ we can use A for other purposes LDX #50 \ Set X = 50 to use as the value for steering left CMP #2 \ If A = 2 then we are steering left, so jump to asst6 BEQ asst6 \ to skip the following instruction LDX #10 \ Set X = 10 to use as the value for steering right \ So we now have the following that we can use to check \ which direction we are steering: \ \ * X = 10 if we are steering right \ \ * X = 50 if we are steering left .asst6 \ We now spend the rest of the routine calculating the \ amount of computer assisted steering (CAS) to apply, \ returning the result in the sign-magnitude number \ (U T) \ \ First, we set the following if we are steering right: \ \ (W V) = (steeringHi steeringLo) + 256 \ \ or the following if we are steering left: \ \ (W V) = (steeringHi steeringLo) - 256 \ \ by first converting (steeringHi steeringLo) from a \ sign-magnitude number to a signed 16-bit number and \ then doing the addition or subtraction LDA steeringLo \ Set V = steeringLo STA V LSR A \ Set the C flag to the sign of steeringLo LDA steeringHi \ Set A = steeringHi \ \ So (A V) = (steeringHi steeringLo) BCC asst7 \ If the C flag is clear then (steeringHi steeringLo) is \ positive, so jump to asst7 as (A V) already has the \ correct sign \ Otherwise (steeringHi steeringLo) is negative, so we \ need to negate (A V) LDA #0 \ Set (A V) = 0 - (A V) SEC \ SBC V \ starting with the low bytes STA V LDA #0 \ And then the high bytes SBC steeringHi .asst7 CLC \ Set (A V) = (A V) + 256 ADC #1 \ = (steeringHi steeringLo) + 256 CPX #50 \ If X <> 50, then we are steering right, so jump to BNE asst8 \ asst8 SBC #2 \ X = 50, so we are steering left, so set: \ \ (A V) = (A V) - 2 * 256 \ = (steeringHi steeringLo) + 256 - 2 * 256 \ = (steeringHi steeringLo) - 256 .asst8 STA W \ Set (W V) = (A V) \ \ So if we are steering right, we have: \ \ (W V) = (steeringHi steeringLo) + 256 \ \ and if we are steering left we have: \ \ (W V) = (steeringHi steeringLo) - 256 LDA xVergeRightLo,X \ Set (A T) = X-th (xVergeRightHi xVergeRightLo) - (W V) SEC \ SBC V \ starting with the low bytes STA T LDA xVergeRightHi,X \ And then the high bytes SBC W PHP \ Store the sign flag for X-th xVergeRight - (W V) on \ the stack, so we can retrieve it below JSR Absolute16Bit \ Set (A T) = |A T| \ = |X-th xVergeRight - (W V)| STA V \ Set (V T) = (A T) \ = |X-th xVergeRight - (W V)| LDY playerSegmentIndex \ Set Y to the index of the player's segment in the \ track segment buffer LDA #60 \ Set A = 60 - playerSpeedHi SEC SBC playerSpeedHi BPL asst9 \ If the result is positive, jump to asst9 to skip the \ following instruction LDA #0 \ Set A = 0, so A is always positive, and is zero if we \ are currently doing more than 60, so: \ \ A = max(0, 60 - playerSpeedHi) .asst9 ASL A \ Set U = 32 * A * 2 ADC #32 \ = 32 + max(0, 60 - playerSpeedHi) * 2 STA U \ \ So U is 32 if we are doing more than 60, and higher \ with lower speeds LDA segmentSteering,Y \ Fetch the carSteering value to steer round the corner \ for the player's track segment AND #%01111111 \ Zero the driving direction in bit 7 CMP #64 \ If A < 64, jump to asst10 to skip the following BCC asst10 \ instruction LDA #2 \ A >= 64, i.e. bit 6 is set, so set A = 2 .asst10 CMP #8 \ If A < 8, jump to asst11 to skip the following BCC asst11 \ instruction LDA #7 \ A >= 8, so set A = 7, i.e. A = min(A, 7) .asst11 \ By now A is between 0 and 7, and is set to 2 if bit 6 \ of segmentSteering was set ASL A \ Set A = A * 16 ASL A \ ASL A \ So A is in the range 0 to 112 ASL A CMP U \ If A < U, jump to asst12 to skip the following BCC asst12 \ instruction STA U \ A >= U, so set U = A, i.e. set U = max(U, A) .asst12 JSR Multiply8x16 \ Set (U T) = U * (V T) / 256 \ = U * |X-th xVergeRight - (W V)| / 256 LDA U \ Set (A T) = (U T) \ = U * |X-th xVergeRight - (W V)| / 256 PLP \ Retrieve the sign of the X-th xVergeRight - (W V) \ calculation that we stored above JSR Absolute16Bit \ Set the sign of (A T) to that of X-th xVergeRight - \ (W V), so we now have: \ \ (A T) = U * (X-th xVergeRight - (W V)) / 256 STA U \ Set (U T) = (A T) \ = U * (X-th xVergeRight - (W V)) / 256 LDA T \ Clear bit 0 of (U T) AND #%11111110 STA T LDA steeringLo \ Set the C flag to the sign in bit 0 of steeringLo LSR A BCS asst13 \ If the C flag is set, jump to asst13 to skip the \ following instruction JSR Negate16Bit+2 \ Set (A T) = -(U T) STA U \ Set (U T) = (A T) \ = -(U T) .asst13 LDA steeringLo \ Set A = steeringLo to return from the subroutine JMP keys10 \ Return to the ProcessDrivingKeys routine at keys10 ENDIF