Skip to navigation


Drawing lines: LOIN (Part 6 of 7)

[Apple II version]

Name: LOIN (Part 6 of 7) [Show more] Type: Subroutine Category: Drawing lines Summary: Draw a steep line going up and left or down and right Deep dive: Bresenham's line algorithm
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. If we get here, then: * The line is going up and left (no swap) or down and right (swap) * X1 < X2 and Y1 >= Y2 * Draw from (X1, Y1) at top left to (X2, Y2) at bottom right, omitting the first pixel
CLC ; Clear the C flag LDA SWAP ; If SWAP = 0 then we didn't swap the coordinates above, BEQ LI17 ; so jump down to LI17 to skip plotting the first pixel DEX ; Decrement the counter in X because we're about to plot ; the first pixel .LIL5 ; We now loop along the line from left to right, using X ; as a decreasing counter, and at each count we plot a ; single pixel using the pixel mask in R LDA R ; Fetch the pixel byte from R EOR (SC),Y ; Store R into screen memory at SC(1 0), using EOR STA (SC),Y ; logic so it merges with whatever is already on-screen .LI17 DEC T2 ; Decrement the pixel row counter within the character ; block, which is in T2 BMI LI22 ; If T2 is negative then the counter just ran down and ; we are no longer within the same character block, so ; jump to LI22 to move to the bottom pixel row in the ; character row above ; We now need to move up into the pixel row above LDA SC+1 ; Subtract 4 from the high byte of SC(1 0), so this does SBC #3 ; the following: STA SC+1 ; ; SC(1 0) = SC(1 0) - $400 ; ; The SBC works because we cleared the C flag above ; ; So this sets SC(1 0) to the address of the pixel row ; above the one we just drew in, as each pixel row ; within the character row is spaced out by $400 bytes ; in screen memory CLC ; Clear the C flag again, as it will have been set by ; the subtraction .LI16 LDA S ; Set S = S + P to update the slope error ADC P STA S BCC LIC5 ; If the addition didn't overflow, jump to LIC5 ASL R ; Shift the single pixel in R to the left to step along ; the x-axis, so the next pixel we plot will be at the ; next x-coordinate along (we shift left because the ; pixels in the high-resolution screen are the opposite ; way around than the bits in the pixel byte) BPL LIC5 ; If the pixel didn't fall out of the left end of the ; pixel bits in R into the palette bit in bit 7, then ; jump to LIC5 LDA #%00000001 ; Otherwise we need to move over to the next character STA R ; block, so set R = %00000001 to move the pixel to the ; left end of the next pixel byte INY ; And increment Y to move on to the next character block ; along to the right .LIC5 DEX ; Decrement the counter in X BNE LIL5 ; If we haven't yet reached the right end of the line, ; loop back to LIL5 to plot the next pixel along LDY YSAV ; Restore Y from YSAV, so that it's preserved RTS ; Return from the subroutine .LI22 ; If we get here then we need to move up into the bottom ; pixel row in the character block above LDA #7 ; Set the pixel line number within the character row STA T2 ; (which we store in T2) to 7, which is the bottom pixel ; row of the character block above STX T ; Store the current character row number in T, so we can ; restore it below LDX T1 ; Decrement the number of the character row in T1, as we DEX ; are moving up a row STX T1 LDA SCTBL,X ; Set SC(1 0) to the X-th entry from (SCTBH2 SCTBL), so STA SC ; it contains the address of the start of the bottom LDA SCTBH2,X ; pixel row in character row X in screen memory (so ; that's the bottom pixel row in the character row we ; just moved up into) ; ; We set the high byte below (though there's no reason ; why it isn't done here) LDX T ; Restore the value of X that we stored, so X contains ; the previous character row number, from before we ; moved up a row (we need to do this as the following ; jump returns us to a point where the previous row ; number is still in X) STA SC+1 ; Set the high byte of SC(1 0) as above JMP LI16 ; Jump back to keep drawing the line