Skip to navigation


Moving: MVS5

[Commodore 64 version]

Name: MVS5 [Show more] Type: Subroutine Category: Moving Summary: Apply a 3.6 degree pitch or roll to an orientation vector Deep dive: Orientation vectors Pitching and rolling by a fixed angle
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MVEIT (Part 8 of 9) calls MVS5

Pitch or roll a ship by a small, fixed amount (1/16 radians, or 3.6 degrees), in a specified direction, by rotating the orientation vectors. The vectors to rotate are given in X and Y, and the direction of the rotation is given in RAT2. The calculation is as follows: * If the direction is positive: X = X * (1 - 1/512) + Y / 16 Y = Y * (1 - 1/512) - X / 16 * If the direction is negative: X = X * (1 - 1/512) - Y / 16 Y = Y * (1 - 1/512) + X / 16 So if X = 15 (roofv_x), Y = 21 (sidev_x) and RAT2 is positive, it does this: roofv_x = roofv_x * (1 - 1/512) + sidev_x / 16 sidev_x = sidev_x * (1 - 1/512) - roofv_x / 16
Arguments: X The first vector to rotate: * If X = 15, rotate roofv_x * If X = 17, rotate roofv_y * If X = 19, rotate roofv_z * If X = 21, rotate sidev_x * If X = 23, rotate sidev_y * If X = 25, rotate sidev_z Y The second vector to rotate: * If Y = 9, rotate nosev_x * If Y = 11, rotate nosev_y * If Y = 13, rotate nosev_z * If Y = 21, rotate sidev_x * If Y = 23, rotate sidev_y * If Y = 25, rotate sidev_z RAT2 The direction of the pitch or roll to perform, positive or negative (i.e. the sign of the roll or pitch counter in bit 7)
.MVS5 LDA INWK+1,X ; Fetch roofv_x_hi, clear the sign bit, divide by 2 and AND #%01111111 ; store in T, so: LSR A ; STA T ; T = |roofv_x_hi| / 2 ; = |roofv_x| / 512 ; ; The above is true because: ; ; |roofv_x| = |roofv_x_hi| * 256 + roofv_x_lo ; ; so: ; ; |roofv_x| / 512 = |roofv_x_hi| * 256 / 512 ; + roofv_x_lo / 512 ; = |roofv_x_hi| / 2 LDA INWK,X ; Now we do the following subtraction: SEC ; SBC T ; (S R) = (roofv_x_hi roofv_x_lo) - |roofv_x| / 512 STA R ; = (1 - 1/512) * roofv_x ; ; by doing the low bytes first LDA INWK+1,X ; And then the high bytes (the high byte of the right SBC #0 ; side of the subtraction being 0) STA S LDA INWK,Y ; Set P = nosev_x_lo STA P LDA INWK+1,Y ; Fetch the sign of nosev_x_hi (bit 7) and store in T AND #%10000000 STA T LDA INWK+1,Y ; Fetch nosev_x_hi into A and clear the sign bit, so AND #%01111111 ; A = |nosev_x_hi| LSR A ; Set (A P) = (A P) / 16 ROR P ; = |nosev_x_hi nosev_x_lo| / 16 LSR A ; = |nosev_x| / 16 ROR P LSR A ROR P LSR A ROR P ORA T ; Set the sign of A to the sign in T (i.e. the sign of ; the original nosev_x), so now: ; ; (A P) = nosev_x / 16 EOR RAT2 ; Give it the sign as if we multiplied by the direction ; by the pitch or roll direction STX Q ; Store the value of X so it can be restored after the ; call to ADD JSR ADD ; (A X) = (A P) + (S R) ; = +/-nosev_x / 16 + (1 - 1/512) * roofv_x STA K+1 ; Set K(1 0) = (1 - 1/512) * roofv_x +/- nosev_x / 16 STX K LDX Q ; Restore the value of X from before the call to ADD LDA INWK+1,Y ; Fetch nosev_x_hi, clear the sign bit, divide by 2 and AND #%01111111 ; store in T, so: LSR A ; STA T ; T = |nosev_x_hi| / 2 ; = |nosev_x| / 512 LDA INWK,Y ; Now we do the following subtraction: SEC ; SBC T ; (S R) = (nosev_x_hi nosev_x_lo) - |nosev_x| / 512 STA R ; = (1 - 1/512) * nosev_x ; ; by doing the low bytes first LDA INWK+1,Y ; And then the high bytes (the high byte of the right SBC #0 ; side of the subtraction being 0) STA S LDA INWK,X ; Set P = roofv_x_lo STA P LDA INWK+1,X ; Fetch the sign of roofv_x_hi (bit 7) and store in T AND #%10000000 STA T LDA INWK+1,X ; Fetch roofv_x_hi into A and clear the sign bit, so AND #%01111111 ; A = |roofv_x_hi| LSR A ; Set (A P) = (A P) / 16 ROR P ; = |roofv_x_hi roofv_x_lo| / 16 LSR A ; = |roofv_x| / 16 ROR P LSR A ROR P LSR A ROR P ORA T ; Set the sign of A to the opposite sign to T (i.e. the EOR #%10000000 ; sign of the original -roofv_x), so now: ; ; (A P) = -roofv_x / 16 EOR RAT2 ; Give it the sign as if we multiplied by the direction ; by the pitch or roll direction STX Q ; Store the value of X so it can be restored after the ; call to ADD JSR ADD ; (A X) = (A P) + (S R) ; = -/+roofv_x / 16 + (1 - 1/512) * nosev_x STA INWK+1,Y ; Set nosev_x = (1-1/512) * nosev_x -/+ roofv_x / 16 STX INWK,Y LDX Q ; Restore the value of X from before the call to ADD LDA K ; Set roofv_x = K(1 0) STA INWK,X ; = (1-1/512) * roofv_x +/- nosev_x / 16 LDA K+1 STA INWK+1,X RTS ; Return from the subroutine