Skip to navigation


Drawing circles: BLINE

[Commodore 64 version]

Name: BLINE [Show more] Type: Subroutine Category: Drawing circles Summary: Draw a circle segment and add it to the ball line heap Deep dive: The ball line heap Drawing circles
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * CIRCLE2 calls BLINE * PLS22 calls BLINE

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) K4(1 0) Pixel y-coordinate of the centre of the circle K5(1 0) Screen x-coordinate of the previous point added to the ball line heap (if this is not the first point) K5(3 2) Screen y-coordinate of the previous point added to the ball line heap (if this is not the first point)
Returns: CNT CNT is updated to CNT + STP A The new value of CNT K5(1 0) Screen x-coordinate of the point that we just added to the ball line heap K5(3 2) Screen y-coordinate of the point that we just added to the ball line heap 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 x-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 ; screen anyway, so jump to BL5, to avoid drawing and ; 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 ; jump to BL9 to skip the following swap 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 ADC STP STA CNT RTS ; Return from the subroutine