This code appears in the following versions (click to see it in the source code):

Code variations between these versions are shown below.

.STPX LDX X1 \ Set X = X1 CPX X2 \ If X1 < X2, jump down to LI3, as the coordinates are BCC LI3 \ already in the order that we want DEC SWAP \ Otherwise decrement SWAP from 0 to &FF, to denote that \ we are swapping the coordinates around LDA X2 \ Swap the values of X1 and X2 STA X1 STX X2 TAX \ Set X = X1 LDA Y2 \ Swap the values of Y1 and Y2 LDY Y1 STA Y1 STY Y2 .LI3 \ By this point we know the line is horizontal-ish and \ X1 < X2, so we're going from left to right as we go \ from X1 to X2Name: LOIN (Part 2 of 7) Type: Subroutine Category: Drawing lines Summary: Draw a line: Line has a shallow gradient, step right along x-axis Deep dive: Bresenham's line algorithm

This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages. If we get here, then: * |delta_y| < |delta_x| * The line is closer to being horizontal than vertical * We are going to step right along the x-axis * We potentially swap coordinates to make sure X1 < X2

LDA Y1 \ Set Y = Y1 mod 8, which is the pixel row within the AND #7 \ character block at which we want to draw the start of TAY \ our line (as each character block has 8 rows)

This variation is blank in the Electron version.

Tap on a version to expand it, and tap it again to show to all variations.

Cassette, Flight, Docked, 6502SP, Master

STA SC \ Store this value in SC, so SC(1 0) now contains the \ screen address of the far left end (x-coordinate = 0) \ of the horizontal pixel row that we want to draw the \ start of our line on

Part 2 of the LOIN routine in the advanced versions uses logarithms to speed up the multiplication.

Tap on a version to expand it, and tap it again to show to all variations.

The Master version omits half of the logarithm algorithm when compared to the 6502SP version.

See below for more variations related to this code.

This variation is blank in the Cassette, Disc (flight), Disc (docked), Master and Electron versions.

6502SP

BMI LIlog4 \ If A > 127, jump to LIlog4

Code variation 7 of 9

See variation 6 above for details.

This variation is blank in the Cassette, Disc (flight), Disc (docked) and Electron versions.

6502SP, Master

LDX Q \ And then subtracting the high bytes of log(Q) - log(P) LDA log,X \ so now A contains the high byte of log(Q) - log(P) LDX P SBC log,X BCS LIlog5 \ If the subtraction fitted into one byte and didn't \ underflow, then log(Q) - log(P) < 256, so we jump to \ LIlog5 to return a result of 255 TAX \ Otherwise we set A to the A-th entry from the antilog LDA antilog,X \ table so the result of the division is now in A JMP LIlog6 \ Jump to LIlog6 to return the result .LIlog5 LDA #255 \ The division is very close to 1, so set A to the BNE LIlog6 \ closest possible answer to 256, i.e. 255, and jump to \ LIlog6 to return the result (this BNE is effectively a \ JMP as A is never zero) .LIlog7

Code variation 8 of 9

See variation 6 above for details.

This variation is blank in the Cassette, Disc (flight), Disc (docked) and Electron versions.

Tap on a version to expand it, and tap it again to show to all variations.

Code variation 9 of 9

See variation 6 above for details.

This variation is blank in the Cassette, Disc (flight), Disc (docked) and Electron versions.

6502SP, Master

.LIlog6 STA Q \ Store the result of the division in Q, so we have: \ \ Q = |delta_y| / |delta_x| LDX P \ Set X = P \ = |delta_x| BEQ LIEXS \ If |delta_x| = 0, return from the subroutine, as LIEXS \ contains a BEQ LIEX instruction, and LIEX contains an \ RTS INX \ Set X = P + 1 \ = |delta_x| + 1 \ \ We add 1 so we can skip the first pixel plot if the \ line is being drawn with swapped coordinates LDA Y2 \ If Y2 < Y1 then skip the following instruction CMP Y1 BCC P%+5 JMP DOWN \ Y2 >= Y1, so jump to DOWN, as we need to draw the line \ to the right and down