BBC Micro Elite

# Drawing circles: BLINE

```       Name: BLINE                                             [View in context]
Type: Subroutine
Category: Drawing circles
Summary: Draw a circle segment and add it to the ball line heap
Deep dive: The ball line heap

Draw a single segment of a circle, adding the point to the ball line heap.

Arguments:

CNT                  The number of this segment

STP                  The step size for the circle

K6(1 0)              The x-coordinate of the new point on the circle, as
a screen coordinate

(T X)                The y-coordinate of the new point on the circle, as
an offset from the centre of the circle

FLAG                 Set to &FF for the first call, so it sets up the first
point in the heap but waits until the second call before
drawing anything (as we need two points, i.e. two calls,
before we can draw a line)

K3(1 0)              Pixel x-coordinate of the centre of the circle

K4(1 0)              Pixel y-coordinate of the centre of the circle

SWAP                 If non-zero, we swap (X1, Y1) and (X2, Y2)

Returns:

CNT                  CNT is updated to CNT + STP

A                    The new value of CNT

FLAG                 Set to 0

.BLINE

TXA                    \ Set K6(3 2) = (T X) + K4(1 0)
ADC K4                 \             = y-coord of centre + y-coord of new point
STA K6+2               \
LDA K4+1               \ so K6(3 2) now contains the y-coordinate of the new
ADC T                  \ point on the circle but as a screen coordinate, to go
STA K6+3               \ along with the screen y-coordinate in K6(1 0)

LDA FLAG               \ If FLAG = 0, jump down to BL1
BEQ BL1

INC FLAG               \ Flag is &FF so this is the first call to BLINE, so
\ increment FLAG to set it to 0, as then the next time
\ we call BLINE it can draw the first line, from this
\ point to the next

.BL5

\ The following inserts a &FF marker into the LSY2 line
\ heap to indicate that the next call to BLINE should
\ store both the (X1, Y1) and (X2, Y2) points. We do
\ this on the very first call to BLINE (when FLAG is
\ &FF), and on subsequent calls if the segment does not
\ fit on-screen, in which case we don't draw or store
\ that segment, and we start a new segment with the next
\ call to BLINE that does fit on-screen

LDY LSP                \ If byte LSP-1 of LSY2 = &FF, jump to BL7 to tidy up
LDA #&FF               \ and return from the subroutine, as the point that has
CMP LSY2-1,Y           \ been passed to BLINE is the start of a segment, so all
BEQ BL7                \ we need to do is save the coordinate in K5, without
\ moving the pointer in LSP

STA LSY2,Y             \ Otherwise we just tried to plot a segment but it
\ didn't fit on-screen, so put the &FF marker into the
\ heap for this point, so the next call to BLINE starts
\ a new segment

INC LSP                \ Increment LSP to point to the next point in the heap

BNE BL7                \ Jump to BL7 to tidy up and return from the subroutine
\ (this BNE is effectively a JMP, as LSP will never be
\ zero)

.BL1

LDA K5                 \ Set XX15 = K5 = x_lo of previous point
STA XX15

LDA K5+1               \ Set XX15+1 = K5+1 = x_hi of previous point
STA XX15+1

LDA K5+2               \ Set XX15+2 = K5+2 = y_lo of previous point
STA XX15+2

LDA K5+3               \ Set XX15+3 = K5+3 = y_hi of previous point
STA XX15+3

LDA K6                 \ Set XX15+4 = x_lo of new point
STA XX15+4

LDA K6+1               \ Set XX15+5 = x_hi of new point
STA XX15+5

LDA K6+2               \ Set XX12 = y_lo of new point
STA XX12

LDA K6+3               \ Set XX12+1 = y_hi of new point
STA XX12+1

JSR LL145              \ Call LL145 to see if the new line segment needs to be
\ clipped to fit on-screen, returning the clipped line's
\ end-points in (X1, Y1) and (X2, Y2)

BCS BL5                \ If the C flag is set then the line is not visible on
\ storing this line

LDA SWAP               \ If SWAP = 0, then we didn't have to swap the line
BEQ BL9                \ coordinates around during the clipping process, so

LDA X1                 \ Otherwise the coordinates were swapped by the call to,
LDY X2                 \ LL145 above, so we swap (X1, Y1) and (X2, Y2) back
STA X2                 \ again
STY X1
LDA Y1
LDY Y2
STA Y2
STY Y1

.BL9

LDY LSP                \ Set Y = LSP

LDA LSY2-1,Y           \ If byte LSP-1 of LSY2 is not &FF, jump down to BL8
CMP #&FF               \ to skip the following (X1, Y1) code
BNE BL8

\ Byte LSP-1 of LSY2 is &FF, which indicates that we
\ need to store (X1, Y1) in the heap

LDA X1                 \ Store X1 in the LSP-th byte of LSX2
STA LSX2,Y

LDA Y1                 \ Store Y1 in the LSP-th byte of LSY2
STA LSY2,Y

INY                    \ Increment Y to point to the next byte in LSX2/LSY2

.BL8

LDA X2                 \ Store X2 in the LSP-th byte of LSX2
STA LSX2,Y

LDA Y2                 \ Store Y2 in the LSP-th byte of LSX2
STA LSY2,Y

INY                    \ Increment Y to point to the next byte in LSX2/LSY2

STY LSP                \ Update LSP to point to the same as Y

JSR LOIN               \ Draw a line from (X1, Y1) to (X2, Y2)

LDA XX13               \ If XX13 is non-zero, jump up to BL5 to add a &FF
BNE BL5                \ marker to the end of the line heap. XX13 is non-zero
\ after the call to the clipping routine LL145 above if
\ the end of the line was clipped, meaning the next line
\ sent to BLINE can't join onto the end but has to start
\ a new segment, and that's what inserting the &FF
\ marker does

.BL7

LDA K6                 \ Copy the data for this step point from K6(3 2 1 0)
STA K5                 \ into K5(3 2 1 0), for use in the next call to BLINE:
LDA K6+1               \
STA K5+1               \   * K5(1 0) = screen x-coordinate of this point
LDA K6+2               \
STA K5+2               \   * K5(3 2) = screen y-coordinate of this point
LDA K6+3               \
STA K5+3               \ They now become the "previous point" in the next call

LDA CNT                \ Set CNT = CNT + STP
CLC