Skip to navigation


Maths (Arithmetic): LL123

[NES version, Bank 1]

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 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 ADC #1 ; TAX ; The addition works 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