Skip to navigation

Elite on the BBC Micro and NES

Drawing lines: LL145 (Part 3 of 4)

[NES version, Bank 1]

Name: LL145 (Part 3 of 4) [Show more] Type: Subroutine Category: Drawing lines Summary: Clip line: Calculate the line's gradient Deep dive: Line-clipping Extended screen coordinates
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
.LL115 TYA ; Store Y on the stack so we can preserve it through the PHA ; call to this subroutine LDA XX15+4 ; Set XX12+2 = x2_lo - x1_lo SEC SBC XX15 STA XX12+2 LDA XX15+5 ; Set XX12+3 = x2_hi - x1_hi SBC XX15+1 STA XX12+3 LDA XX12 ; Set XX12+4 = y2_lo - y1_lo SEC SBC XX15+2 STA XX12+4 LDA XX12+1 ; Set XX12+5 = y2_hi - y1_hi SBC XX15+3 STA XX12+5 ; So we now have: ; ; delta_x in XX12(3 2) ; delta_y in XX12(5 4) ; ; where the delta is (x1, y1) - (x2, y2)) EOR XX12+3 ; Set S = the sign of delta_x * the sign of delta_y, so STA S ; if bit 7 of S is set, the deltas have different signs LDA XX12+5 ; If delta_y_hi is positive, jump down to LL110 to skip BPL LL110 ; the following LDA #0 ; Otherwise flip the sign of delta_y to make it SEC ; positive, starting with the low bytes SBC XX12+4 STA XX12+4 LDA #0 ; And then doing the high bytes, so now: SBC XX12+5 ; STA XX12+5 ; XX12(5 4) = |delta_y| .LL110 LDA XX12+3 ; If delta_x_hi is positive, jump down to LL111 to skip BPL LL111 ; the following SEC ; Otherwise flip the sign of delta_x to make it LDA #0 ; positive, starting with the low bytes SBC XX12+2 STA XX12+2 LDA #0 ; And then doing the high bytes, so now: SBC XX12+3 ; ; (A XX12+2) = |delta_x| .LL111 ; We now keep halving |delta_x| and |delta_y| until ; both of them have zero in their high bytes TAX ; If |delta_x_hi| is non-zero, skip the following BNE LL112 LDX XX12+5 ; If |delta_y_hi| = 0, jump down to LL113 (as both BEQ LL113 ; |delta_x_hi| and |delta_y_hi| are 0) .LL112 LSR A ; Halve the value of delta_x in (A XX12+2) ROR XX12+2 LSR XX12+5 ; Halve the value of delta_y XX12(5 4) ROR XX12+4 JMP LL111 ; Loop back to LL111 .LL113 ; By now, the high bytes of both |delta_x| and |delta_y| ; are zero STX T ; We know that X = 0 as that's what we tested with a BEQ ; above, so this sets T = 0 LDA XX12+2 ; If delta_x_lo < delta_y_lo, so our line is more CMP XX12+4 ; vertical than horizontal, jump to LL114 BCC LL114 ; If we get here then our line is more horizontal than ; vertical, so it is a shallow slope STA Q ; Set Q = delta_x_lo LDA XX12+4 ; Set A = delta_y_lo JSR LL28 ; Call LL28 to calculate: ; ; R = 256 * A / Q ; = 256 * delta_y_lo / delta_x_lo JMP LL116 ; Jump to LL116, as we now have the line's gradient in R .LL114 ; If we get here then our line is more vertical than ; horizontal, so it is a steep slope LDA XX12+4 ; Set Q = delta_y_lo STA Q LDA XX12+2 ; Set A = delta_x_lo JSR LL28 ; Call LL28 to calculate: ; ; R = 256 * A / Q ; = 256 * delta_x_lo / delta_y_lo DEC T ; T was set to 0 above, so this sets T = $FF when our ; line is steep