Elite on the BBC Micro and NES

# Drawing lines: LOIN (Part 4 of 7)

## [Acorn Electron version]

```       Name: LOIN (Part 4 of 7)                                      [Show more]
Type: Subroutine
Category: Drawing lines
Summary: Draw a shallow line going right and down or left and up
Deep dive: Bresenham's line algorithm
Context: See this subroutine in context in the source code
Variations: See code variations for this subroutine in the different versions
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 right and down (no swap) or left and up (swap)

* X1 < X2 and Y1-1 <= Y2

* Draw from (X1, Y1) at top left to (X2, Y2) at bottom right, omitting the
first pixel

.DOWN

LDA SWAP               \ If SWAP = 0 then we didn't swap the coordinates above,
BEQ LI9                \ so jump down to LI9 to skip plotting the first pixel

DEX                    \ Decrement the counter in X because we're about to plot
\ the first pixel

.LIL3

\ 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

.LI9

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
\ next x-coordinate along

BCC LI10               \ If the pixel didn't fall out of the right end of R

ROR R                  \ Otherwise we need to move over to the next character
\ block, so first rotate R right so the set C flag goes
\ back into the left end, giving %10000000

LDA SC                 \ Add 8 to SC, so SC(1 0) now points to the next
ADC #8                 \ character along to the right
STA SC

BCC LI10               \ If the addition of the low bytes overflowed, increment
INC SC+1               \ the high byte of SC(1 0)

.LI10

LDA S                  \ Set S = S + Q to update the slope error
STA S

INY                    \ Otherwise we just overflowed, so increment Y to move
\ to the pixel line below

CPY #8                 \ If Y < 8 we are still within the same character block,

\ We now need to move down into the character block
\ below, 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 add to SC(1 0)
\
\ We also know the C flag is set, as we didn't take the
\ BCC above, so we can add &13F in order to get the
\ correct result

LDA SC                 \ Set SC(1 0) = SC(1 0) + &140
STA SC                 \ Starting with the low bytes

LDA SC+1               \ And then adding the high bytes
STA SC+1

LDY #0                 \ Set the pixel line to the first line in that character
\ block

.LIC3

DEX                    \ Decrement the counter in X

BNE LIL3               \ If we haven't yet reached the right end of the line,
\ loop back to LIL3 to plot the next pixel along

LDY YSAV               \ Restore Y from YSAV, so that it's preserved

RTS                    \ Return from the subroutine
```