Elite on the BBC Micro and NES

# Drawing lines: LOIN (Part 1 of 7)

## [Acorn Electron version]

```       Name: LOIN (Part 1 of 7)                                      [Show more]
Type: Subroutine
Category: Drawing lines
Summary: Draw a line: Calculate the line gradient in the form of deltas
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: This subroutine is called as follows:
* BLINE calls LOIN
* LASLI calls LOIN
* TTX66 calls LOIN
* WPLS2 calls LOIN
* HLOIN calls via LL30
* LL9 (Part 12 of 12) calls via LL30
* TT15 calls via LL30

This routine draws a line from (X1, Y1) to (X2, Y2). It has multiple stages.
This stage calculates the line deltas.

Arguments:

X1                   The screen x-coordinate of the start of the line

Y1                   The screen y-coordinate of the start of the line

X2                   The screen x-coordinate of the end of the line

Y2                   The screen y-coordinate of the end of the line

Returns:

Y                    Y is preserved

Other entry points:

LL30                 LL30 is a synonym for LOIN and draws a line from
(X1, Y1) to (X2, Y2)

.LL30

SKIP 0                 \ LL30 is a synonym for LOIN
\
\ In the cassette and disc versions of Elite, LL30 and
\ LOIN are synonyms for the same routine, presumably
\ because the two developers each had their own line
\ routines to start with, and then chose one of them for
\ the final game

.LOIN

STY YSAV               \ Store Y into YSAV, so we can preserve it across the
\ call to this subroutine

LDA #128               \ Set S = 128, which is the starting point for the
STA S                  \ slope error (representing half a pixel)

STA SC                 \ Set SC = 128 for use in the pixel calculations below

ASL A                  \ Set SWAP = 0, as %10000000 << 1 = 0
STA SWAP

LDA X2                 \ Set A = X2 - X1
SBC X1                 \       = delta_x
\
\ This subtraction works as the ASL A above sets the C
\ flag

BCS LI1                \ If X2 > X1 then A is already positive and we can skip
\ the next three instructions

EOR #%11111111         \ Negate the result in A by flipping all the bits and
ADC #1                 \ adding 1, i.e. using two's complement to make it
\ positive

.LI1

STA P                  \ Store A in P, so P = |X2 - X1|, or |delta_x|

SEC                    \ Set the C flag, ready for the subtraction below

LDA Y2                 \ Set A = Y2 - Y1
SBC Y1                 \       = delta_y
\
\ This subtraction works as we either set the C flag
\ above, or we skipped that SEC instruction with a BCS

BCS LI2                \ If Y2 > Y1 then A is already positive and we can skip
\ the next two instructions

EOR #%11111111         \ Negate the result in A by flipping all the bits and
ADC #1                 \ adding 1, i.e. using two's complement to make it
\ positive

.LI2

STA Q                  \ Store A in Q, so Q = |Y2 - Y1|, or |delta_y|

CMP P                  \ If Q < P, jump to STPX to step along the x-axis, as
BCC STPX               \ the line is closer to being horizontal than vertical

JMP STPY               \ Otherwise Q >= P so jump to STPY to step along the
\ y-axis, as the line is closer to being vertical than
\ horizontal
```