Elite on the BBC Micro and NES

# Moving: MVT1

## [Acorn Electron version]

```       Name: MVT1                                                    [Show more]
Type: Subroutine
Category: Moving
Summary: Calculate (x_sign x_hi x_lo) = (x_sign x_hi x_lo) + (A R)
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* MVEIT (Part 6 of 9) calls MVT1
* SFS2 calls MVT1
* MVEIT (Part 3 of 9) calls via MVT1-2

Add the signed delta (A R) to a ship's coordinate, along the axis given in X.
Mathematically speaking, this routine translates the ship along a single axis
by a signed delta. Taking the example of X = 0, the x-axis, it does the
following:

(x_sign x_hi x_lo) = (x_sign x_hi x_lo) + (A R)

(In practice, MVT1 is only ever called directly with A = 0 or 128, otherwise
it is always called via MVT-2, which clears A apart from the sign bit. The
routine is written to cope with a non-zero delta_hi, so it supports a full
16-bit delta, but it appears that delta_hi is only ever used to hold the
sign of the delta.)

The comments below assume we are adding delta to the x-axis, though the axis
is determined by the value of X.

Arguments:

(A R)                The signed delta, so A = delta_hi and R = delta_lo

X                    Determines which coordinate axis of INWK to change:

* X = 0 adds the delta to (x_lo, x_hi, x_sign)

* X = 3 adds the delta to (y_lo, y_hi, y_sign)

* X = 6 adds the delta to (z_lo, z_hi, z_sign)

Other entry points:

MVT1-2               Clear bits 0-6 of A before entering MVT1

AND #%10000000         \ Clear bits 0-6 of A

.MVT1

ASL A                  \ Set the C flag to the sign bit of the delta, leaving
\ delta_hi << 1 in A

STA S                  \ Set S = delta_hi << 1
\
\ This also clears bit 0 of S

LDA #0                 \ Set T = just the sign bit of delta (in bit 7)
ROR A
STA T

LSR S                  \ Set S = delta_hi >> 1
\       = |delta_hi|
\
\ This also clear the C flag, as we know that bit 0 of
\ S was clear before the LSR

EOR INWK+2,X           \ If T EOR x_sign has bit 7 set, then x_sign and delta

\ At this point, we know x_sign and delta have the same
\ sign, that sign is in T, and S contains |delta_hi|,
\ so now we want to do:
\
\   (x_sign x_hi x_lo) = (x_sign x_hi x_lo) + (S R)
\
\ and then set the sign of the result to the same sign
\ as x_sign and delta

LDA R                  \ First we add the low bytes, so:
STA INWK,X             \   x_lo = x_lo + R

LDA S                  \ Then we add the high bytes:
STA INWK+1,X           \   x_hi = x_hi + S

LDA INWK+2,X           \ And finally we add any carry into x_sign, and if the
ADC #0                 \ sign of x_sign and delta in T is negative, make sure
ORA T                  \ the result is negative (by OR'ing with T)
STA INWK+2,X

RTS                    \ Return from the subroutine

.MV10

\ If we get here, we know x_sign and delta have
\ |delta_hi| in S, so now we want to do:
\
\   (x_sign x_hi x_lo) = (x_sign x_hi x_lo) - (S R)
\
\ and then set the sign of the result according to
\ the signs of x_sign and delta

LDA INWK,X             \ First we subtract the low bytes, so:
SEC                    \
SBC R                  \   x_lo = x_lo - R
STA INWK,X

LDA INWK+1,X           \ Then we subtract the high bytes:
SBC S                  \
STA INWK+1,X           \   x_hi = x_hi - S

LDA INWK+2,X           \ And finally we subtract any borrow from bits 0-6 of
AND #%01111111         \ x_sign, and give the result the opposite sign bit to T
SBC #0                 \ (i.e. give it the sign of the original x_sign)
ORA #%10000000
EOR T
STA INWK+2,X

BCS MV11               \ If the C flag is set by the above SBC, then our sum
\ above didn't underflow and is correct - to put it
\ another way, (x_sign x_hi x_lo) >= (S R) so the result
\ should indeed have the same sign as x_sign, so jump to
\ MV11 to return from the subroutine

\ Otherwise our subtraction underflowed because
\ (x_sign x_hi x_lo) < (S R), so we now need to flip the
\ subtraction around by using two's complement to this:
\
\   (S R) - (x_sign x_hi x_lo)
\
\ and then we need to give the result the same sign as
\ (S R), the delta, as that's the dominant figure in the
\ sum

LDA #1                 \ First we subtract the low bytes, so:
SBC INWK,X             \
STA INWK,X             \   x_lo = 1 - x_lo

LDA #0                 \ Then we subtract the high bytes:
SBC INWK+1,X           \
STA INWK+1,X           \   x_hi = 0 - x_hi

LDA #0                 \ And then we subtract the sign bytes:
SBC INWK+2,X           \
\   x_sign = 0 - x_sign

AND #%01111111         \ Finally, we set the sign bit to the sign in T, the
ORA T                  \ sign of the original delta, as the delta is the
STA INWK+2,X           \ dominant figure in the sum

.MV11

RTS                    \ Return from the subroutine
```