Skip to navigation


Drawing lines: LOIN (Part 7 of 7)

[Commodore 64 version]

Name: LOIN (Part 7 of 7) [Show more] Type: Subroutine Category: Drawing lines Summary: Draw a steep line going up and right or down and left Deep dive: Bresenham's line algorithm
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * HLOIN calls via HL6

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 right (no swap) or down and left (swap) * X1 >= X2 and Y1 >= Y2 * Draw from (X1, Y1) at bottom left to (X2, Y2) at top right, omitting the first pixel
Other entry points: HL6 Contains an RTS
.LFT LDA SWAP ; If SWAP = 0 then we didn't swap the coordinates above, BEQ LI18 ; so jump down to LI18 to skip plotting the first pixel DEX ; Decrement the counter in X because we're about to plot ; the first pixel .LIL6 LDA R2 ; Fetch the pixel byte from R2 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 .LI18 DEY ; Decrement Y to step up along the y-axis BPL LI19 ; If Y is positive we are still within the same ; character block, so skip to LI19 ; We now need to move up into the character block above, ; and each character row in screen memory takes up $140 ; bytes ($100 for the visible part and $20 for each of ; the blank borders on the side of the screen), so ; that's what we need to subtract from SC(1 0) ; ; We also know the C flag is clear, as we call LFT with ; a BCC, so we can subtract $13F in order to get the ; correct result LDA SC ; Set SC(1 0) = SC(1 0) - $140 SBC #$3F ; STA SC ; Starting with the low bytes LDA SCH ; And then subtracting the high bytes SBC #$01 STA SCH LDY #7 ; Set the pixel line to the last line in that character ; block .LI19 LDA S2 ; Set S2 = S2 + P2 to update the slope error ADC P2 STA S2 BCC LIC6 ; If the addition didn't overflow, jump to LIC6 ASL R2 ; Otherwise we just overflowed, so shift the single ; pixel in R2 to the left, so the next pixel we plot ; will be at the previous x-coordinate BCC LIC6 ; If the pixel didn't fall out of the left end of R2 ; into the C flag, then jump to LIC6 ROL R2 ; Otherwise we need to move over to the next character ; block, so first rotate R2 left so the set C flag goes ; back into the right end, giving %0000001 LDA SC ; Subtract 7 from SC, so SC(1 0) now points to the SBC #7 ; previous character along to the left STA SC BCS P%+4 ; If the subtraction of the low bytes of SC underflowed, DEC SCH ; decrement the high byte CLC ; Clear the C flag so it doesn't affect the additions ; below .LIC6 DEX ; Decrement the counter in X BNE LIL6 ; If we haven't yet reached the left end of the line, ; loop back to LIL6 to plot the next pixel along LDY YSAV ; Restore Y from YSAV, so that it's preserved .HL6 RTS ; Return from the subroutine