Skip to navigation

Elite on the BBC Micro and NES

Moving: MVEIT (Part 5 of 9)

[NES version, Bank 0]

Name: MVEIT (Part 5 of 9) [Show more] Type: Subroutine Category: Moving Summary: Move current ship: Rotate ship's location by our pitch and roll Deep dive: Rotating the universe
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

This routine has multiple stages. This stage does the following: * Rotate the ship's location in space by the amount of pitch and roll of our ship. See below for a deeper explanation of this routine
LDX ALP1 ; Fetch the magnitude of the current roll into X, so ; if the roll angle is alpha, X contains |alpha| LDA INWK ; Set P = ~x_lo (i.e. with all its bits flipped) so that EOR #%11111111 ; we can pass x_lo to MLTU2 below) STA P LDA INWK+1 ; Set A = x_hi JSR MLTU2-2 ; Set (A P+1 P) = (A ~P) * X ; = (x_hi x_lo) * alpha STA P+2 ; Store the high byte of the result in P+2, so we now ; have: ; ; P(2 1 0) = (x_hi x_lo) * alpha LDA ALP2+1 ; Fetch the flipped sign of the current roll angle alpha EOR INWK+2 ; from ALP2+1 and EOR with byte #2 (x_sign), so if the ; flipped roll angle and x_sign have the same sign, A ; will be positive, else it will be negative. So A will ; contain the sign bit of x_sign * flipped alpha sign, ; which is the opposite to the sign of the above result, ; so we now have: ; ; (A P+2 P+1) = - (x_sign x_hi x_lo) * alpha / 256 LDX #3 ; Set (A P+2 P+1) = (y_sign y_hi y_lo) + (A P+2 P+1) JSR MVT6 ; = y - x * alpha / 256 STA K2+3 ; Set K2(3) = A = the sign of the result SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 LDA P+1 ; Set K2(1) = P+1, the low byte of the result STA K2+1 EOR #%11111111 ; Set P = ~K2+1 (i.e. with all its bits flipped) so STA P ; that we can pass K2+1 to MLTU2 below) LDA P+2 ; Set K2(2) = A = P+2 STA K2+2 ; So we now have result 1 above: ; ; K2(3 2 1) = (A P+2 P+1) ; = y - x * alpha / 256 LDX BET1 ; Fetch the magnitude of the current pitch into X, so ; if the pitch angle is beta, X contains |beta| JSR MLTU2-2 ; Set (A P+1 P) = (A ~P) * X ; = K2(2 1) * beta STA P+2 ; Store the high byte of the result in P+2, so we now ; have: ; ; P(2 1 0) = K2(2 1) * beta LDA K2+3 ; Fetch the sign of the above result in K(3 2 1) from EOR BET2 ; K2+3 and EOR with BET2, the sign of the current pitch ; rate, so if the pitch and K(3 2 1) have the same sign, ; A will be positive, else it will be negative. So A ; will contain the sign bit of K(3 2 1) * beta, which is ; the same as the sign of the above result, so we now ; have: ; ; (A P+2 P+1) = K2(3 2 1) * beta / 256 LDX #6 ; Set (A P+2 P+1) = (z_sign z_hi z_lo) + (A P+2 P+1) JSR MVT6 ; = z + K2 * beta / 256 STA INWK+8 ; Set z_sign = A = the sign of the result SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 LDA P+1 ; Set z_lo = P+1, the low byte of the result STA INWK+6 EOR #%11111111 ; Set P = ~z_lo (i.e. with all its bits flipped) so that STA P ; we can pass z_lo to MLTU2 below) LDA P+2 ; Set z_hi = P+2 STA INWK+7 ; So we now have result 2 above: ; ; (z_sign z_hi z_lo) = (A P+2 P+1) ; = z + K2 * beta / 256 JSR MLTU2 ; MLTU2 doesn't change Q, and Q was set to beta in ; the previous call to MLTU2, so this call does: ; ; (A P+1 P) = (A ~P) * Q ; = (z_hi z_lo) * beta STA P+2 ; Set P+2 = A = the high byte of the result, so we ; now have: ; ; P(2 1 0) = (z_hi z_lo) * beta LDA K2+3 ; Set y_sign = K2+3 STA INWK+5 EOR BET2 ; EOR y_sign with BET2, the sign of the current pitch EOR INWK+8 ; rate, and z_sign. If the result is positive jump to BPL MV43 ; MV43, otherwise this means beta * z and y have ; different signs, i.e. P(2 1) and K2(3 2 1) have ; different signs, so we need to add them in order to ; calculate K2(2 1) - P(2 1) LDA P+1 ; Set (y_hi y_lo) = K2(2 1) + P(2 1) ADC K2+1 STA INWK+3 LDA P+2 ADC K2+2 STA INWK+4 JMP MV44 ; Jump to MV44 to continue the calculation .MV43 SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 LDA K2+1 ; Reversing the logic above, we need to subtract P(2 1) SBC P+1 ; and K2(3 2 1) to calculate K2(2 1) - P(2 1), so this STA INWK+3 ; sets (y_hi y_lo) = K2(2 1) - P(2 1) LDA K2+2 SBC P+2 STA INWK+4 BCS MV44 ; If the above subtraction did not underflow, then ; jump to MV44, otherwise we need to negate the result LDA #1 ; Negate (y_sign y_hi y_lo) using two's complement, SBC INWK+3 ; first doing the low bytes: STA INWK+3 ; ; y_lo = 1 - y_lo LDA #0 ; Then the high bytes: SBC INWK+4 ; STA INWK+4 ; y_hi = 0 - y_hi LDA INWK+5 ; And finally flip the sign in y_sign EOR #%10000000 STA INWK+5 .MV44 SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 ; So we now have result 3 above: ; ; (y_sign y_hi y_lo) = K2(2 1) - P(2 1) ; = K2 - beta * z LDX ALP1 ; Fetch the magnitude of the current roll into X, so ; if the roll angle is alpha, X contains |alpha| LDA INWK+3 ; Set P = ~y_lo (i.e. with all its bits flipped) so that EOR #$FF ; we can pass y_lo to MLTU2 below) STA P LDA INWK+4 ; Set A = y_hi JSR MLTU2-2 ; Set (A P+1 P) = (A ~P) * X ; = (y_hi y_lo) * alpha STA P+2 ; Store the high byte of the result in P+2, so we now ; have: ; ; P(2 1 0) = (y_hi y_lo) * alpha LDA ALP2 ; Fetch the correct sign of the current roll angle alpha EOR INWK+5 ; from ALP2 and EOR with byte #5 (y_sign), so if the ; correct roll angle and y_sign have the same sign, A ; will be positive, else it will be negative. So A will ; contain the sign bit of x_sign * correct alpha sign, ; which is the same as the sign of the above result, ; so we now have: ; ; (A P+2 P+1) = (y_sign y_hi y_lo) * alpha / 256 LDX #0 ; Set (A P+2 P+1) = (x_sign x_hi x_lo) + (A P+2 P+1) JSR MVT6 ; = x + y * alpha / 256 STA INWK+2 ; Set x_sign = A = the sign of the result LDA P+2 ; Set x_hi = P+2, the high byte of the result STA INWK+1 LDA P+1 ; Set x_lo = P+1, the low byte of the result STA INWK ; So we now have result 4 above: ; ; x = x + alpha * y ; ; and the rotation of (x, y, z) is done