Elite on the BBC Micro

Maths (Arithmetic): LL123 [Elite-A, Parasite]

```       Name: LL123                                                   [Show more]
Type: Subroutine
Category: Maths (Arithmetic)
Summary: Calculate (Y X) = (S R) / XX12+2 or (S R) * XX12+2
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* LL118 calls LL123
* LL120 calls entry point LL121
* LL120 calls entry point LL133

Calculate the following:

* If T = 0,  calculate (Y X) = (S R) / XX12+2

* If T <> 0, calculate (Y X) = (S R) * XX12+2

giving (Y X) the opposite sign to the slope direction in XX12+3.

Arguments:

XX12+2               The line's gradient * 256 (so 1.0 = 256)

XX12+3               The direction of slope:

* Bit 7 clear means top left to bottom right

* Bit 7 set means top right to bottom left

Other entry points:

LL121                Calculate (Y X) = (S R) / Q and set the sign to the
opposite of the top byte on the stack

LL133                Negate (Y X) and return from the subroutine

LL128                Contains an RTS

.LL123

JSR LL129              \ Call LL129 to do the following:
\
\   Q = XX12+2
\     = line gradient
\
\   A = S EOR XX12+3
\     = S EOR slope direction
\
\   (S R) = |S R|
\
\ So A contains the sign of S * slope direction

PHA                    \ Store A on the stack so we can use it later

LDX T                  \ If T is non-zero, so it's more horizontal than
BNE LL122              \ vertical, jump up to LL122 to calculate this instead:
\
\   (Y X) = (S R) * Q

.LL121

\ The following calculates:
\
\   (Y X) = (S R) / Q
\
\ using the same shift-and-subtract algorithm that's
\ documented in TIS2

LDA #%11111111         \ Set Y = %11111111
TAY

ASL A                  \ Set X = %11111110
TAX

\ This sets (Y X) = %1111111111111110, so we can rotate
\ through 15 loop iterations, getting a 1 each time, and
\ then getting a 0 on the 16th iteration... and we can
\ also use it to catch our result bits into bit 0 each
\ time

.LL130

ASL R                  \ Shift (S R) to the left
ROL S

LDA S                  \ Set A = S

BCS LL131              \ If bit 7 of S was set, then jump straight to the
\ subtraction

CMP Q                  \ If A < Q (i.e. S < Q), skip the following subtractions
BCC LL132

.LL131

SBC Q                  \ A >= Q (i.e. S >= Q) so set:
STA S                  \
\   S = (A R) - Q
\     = (S R) - Q
\
\ starting with the low bytes (we know the C flag is
\ set so the subtraction will be correct)

LDA R                  \ And then doing the high bytes
SBC #0
STA R

SEC                    \ Set the C flag to rotate into the result in (Y X)

.LL132

TXA                    \ Rotate the counter in (Y X) to the left, and catch the
ROL A                  \ result bit into bit 0 (which will be a 0 if we didn't
TAX                    \ do the subtraction, or 1 if we did)
TYA
ROL A
TAY

BCS LL130              \ If we still have set bits in (Y X), loop back to LL130
\ to do the next iteration of 15, until we have done the
\ whole division

PLA                    \ Restore A, which we calculated above, from the stack

BMI LL128              \ If A is negative jump to LL128 to return from the
\ subroutine with (Y X) as is

.LL133

TXA                    \ Otherwise negate (Y X) using two's complement by first
EOR #%11111111         \ setting the low byte to ~X + 1