Skip to navigation

Elite on the BBC Micro and NES

Maths (Arithmetic): LL123

[BBC Master version]

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 Variations: See code variations for this subroutine in the different versions References: This subroutine is called as follows: * LL118 calls LL123 * LL120 calls via LL121 * LL120 calls via LL133

Calculate the following: * If T = 0, this is a shallow slope, so calculate (Y X) = (S R) / XX12+2 * If T <> 0, this is a steep slope, so 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 T The gradient of slope: * 0 if it's a shallow slope * &FF if it's a steep slope
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, then it's a steep slope, so jump up BNE LL122 \ 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 \CLC \ ADC #1 \ The CLC instruction is commented out in the original TAX \ source. It would have no effect as we know the C flag \ is clear from when we passed through the BCS above TYA \ Then set the high byte to ~Y + C EOR #%11111111 ADC #0 TAY .LL128 RTS \ Return from the subroutine