Skip to navigation


Drawing lines: LOIN (Part 7 of 7)

[Apple II 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 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 .LI18 DEC T2 ; Decrement the pixel row counter within the character ; block, which is in T2 BMI LI23 ; If T2 is negative then the counter just ran down and ; we are no longer within the same character block, so ; jump to LI23 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 .LI19 LDA S ; Set S = S + P to update the slope error ADC P STA S BCC LIC6 ; If the addition didn't overflow, jump to LIC6 LSR R ; Shift the single pixel in R to the right to step along ; the x-axis, so the next pixel we plot will be at the ; previous x-coordinate to the left (we shift right ; because the pixels in the high-resolution screen are ; the opposite way around than the bits in the pixel ; byte) BCC LIC6 ; If the pixel didn't fall out of the right end of the ; pixel bits in R into the C flag, then jump to LIC6 LDA #%01000000 ; Otherwise we need to move left to the next character STA R ; block, so set R = %01000000 to move the pixel to the ; right end of the next pixel byte, skipping bit 7 as ; that's reserved for the colour palette bit DEY ; And decrement Y to move on to the next character block ; along to the left CLC ; Clear the C flag so it doesn't affect the additions ; if we loop back .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 .LI23 ; 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 LI19 ; Jump back to keep drawing the line