Revs on the BBC Micro

# Drawing objects: FillAfterObject

```       Name: FillAfterObject                                         [Show more]
Type: Subroutine
Category: Drawing objects
Summary: Fill the block to the right of an object
Deep dive: Creating objects from edges
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* DrawObjectEdge (Part 4 of 5) calls FillAfterObject

Arguments:

blockNumber          The dash data block number to draw in (i.e. the block
to the right of the object)

blockOffset          The dash data offset for the bottom of the edge to draw

topTrackLine         Top track line number, i.e. the number of the start byte
in the dash data block

IF _ACORNSOFT OR _4TRACKS

.FillAfterObject

LDA blockNumber        \ Set A to the dash data block number in blockNumber

CMP #40                \ If A >= 40 then this is not a valid dash data block
BCS edge12             \ number, so jump to edge12 to return from the
\ subroutine

\ We now calculate the start address of dash data block
\ A, which will be at dashData + &80 * A (because the
\ dash data blocks occur every &80 bytes from dashData)
\
\ We do this using the following simplification:
\
\     dashData + &80 * A
\   = dashData + 256 / 2 * A
\   = HI(dashData) << 8 + LO(dashData) + A << 7
\
\ LO(dashData) happens to be zero (as dashData = &3000),
\ so we can keep going:
\
\   = HI(dashData) << 8 + A << 7
\   = (HI(dashData) << 1 + A) << 7
\   = ((HI(dashData) << 1 + A) << 8) >> 1
\
\ In other words, if we build a 16-bit number with the
\ high byte set to HI(dashData) << 1 + A, and then shift
\ the whole thing right by one place, we have our result
\
\ We do this below, storing the 16-bit number in (Q P)

CLC                    \ Set A = A + HI(dashData) << 1
\ so our 16-bit number is (A 0), and we want to shift
\ right by one place

LSR A                  \ Shift (A 0) right by 1, shifting bit 0 of A into the
\ C flag

STA Q                  \ Set Q = A, to store the high byte of the result in Q

STA edge9+2            \ Modify the high byte of the address in the instruction
\ at edge9 to Q

LDA #0                 \ Shift the C flag into bit 7 of A, so A now contains
ROR A                  \ the low byte of our result

STA P                  \ Set P = A, to store the low byte of the result in P,
\ giving the result we wanted in (Q P)

STA edge9+1            \ Modify the low byte of the address in the instruction
\ at edge9 to P, so if we have the following:
\
\   LDX &3000,Y -> LDX #(Q P),Y
\
\ This is pseudo-code, but it means we have modified the
\ instruction to load the Y-th byte from the dash data
\ byte of dash data block A (i.e. dash data block
\ blockNumber)

LDY blockOffset        \ Set Y to the dash data offset for the edge to draw

LDA (P),Y              \ Set W to the byte in the dash data offset from this
STA W                  \ block, which is the byte before the actual dash data

LDA #&AA               \ Store &AA in this byte, so it can act as a marker for
STA (P),Y              \ when we work our way through the data below

LDY topTrackLine       \ Set Y to the number of the top track line, so we work
\ down from this byte within the data block, moving down
\ in memory until we reach the marker
\
\ So we are working down the screen, going backwards in
\ memory from byte topTrackLine to the marker that we
\ just placed at the start of the dash data

JMP edge4              \ Jump into the following loop at the entry point edge4
\ to draw the fill from the top byte to the bottom byte

.edge1

\ This part of the loop, between edge1 and edge5, is
\ only used by the GetTyreDashEdge routine, which
\ modifies the loop to copy pixels instead of filling
\ them

CMP #&55               \ If the current byte is &55, then this represents black
BNE edge2              \ (colour 0), so set A = 0 so it's the correct pixel
LDA #0                 \ byte for the current buffer contents

.edge2

STA (R),Y              \ Store the pixel byte we fetched from the screen buffer
\ in the Y-th byte of (S R), which copies the byte from
\ the screen buffer into the address set up in the
\ CopyTyreDashEdges routine (i.e. this copies the edges
\ into tyreRightEdge or dashRightEdge)

.edge3

DEY                    \ Decrement the byte counter to move down the screen
\ within the dash data block

.edge4

LDA (P),Y              \ Fetch the Y-th byte from the dash data block

BNE edge10             \ If the current byte in the screen buffer is non-zero,
\ then it is not empty, so jump to edge10 to move on to
\ the next byte, as we only need to fill empty bytes

.edge5

JSR GetColour          \ The current byte in the screen buffer is zero, which
\ means it should inherit the colour of the byte to the
\ left, so call GetColour to work out what this byte's
\ colour would be on-screen, and put it into A

BNE edge7              \ If the colour byte is non-zero, skip the following
\ instruction

.edge6

LDA #&55               \ Set A = &55, which is the value we use to represent
\ colour 0 (black) in the screen buffer
\
\ Gets modified by the GetTyreDashEdge routine:
\
\   * LDA #0   when GetTyreDashEdge is called with
\              A = 0
\
\   * LDA #&55 when GetTyreDashEdge is called with
\              A = &55

.edge7

STA (P),Y              \ Draw the resulting pixel byte into the screen buffer
\ by writing it to the Y-th byte of the relevant dash
\ data block
\
\ Gets modified by the GetTyreDashEdge routine:
\
\   * STA (R),Y when GetTyreDashEdge is called with
\               X = LO(R)
\
\   * STA (P),Y when GetTyreDashEdge is called with
\               X = LO(P)

.edge8

DEY                    \ Decrement the byte counter to move down the screen
\ within the dash data block

.edge9

LDX &3000,Y            \ Set X to the Y-th byte in the screen buffer, which is
\ the next byte down the screen after the one we just
\ draw
\
\ Gets modified at the start of part 2 as follows:
\
\   LDX &3000,Y -> LDX #(Q P),Y
\
\ In other words, we have modified the instruction to
\ for the edge we are drawing, i.e. load the Y-th byte
\ of dash data block blockNumber

BEQ edge7              \ If the next byte down the screen is zero, then loop
\ back to edge7 to draw the edge in this byte as well,
\ so we keep drawing the edge downwards while the
\ existing contents of the screen buffer are empty

TXA                    \ The next byte down the screen is non-zero, so copy the
\ value into A

.edge10

CMP #&AA               \ Check to see if the next byte is the marker for the
\ bottom of the edge

.edge11

BNE edge3              \ If this is not the marker for the bottom of the edge,
\ loop back to edge3 to draw the next pixel byte over
\ the top of this non-empty byte in the screen buffer
\
\ Gets modified by the GetTyreDashEdge routine:
\
\   * BNE edge1 when GetTyreDashEdge is called with
\               Y = &DF
\
\   * BNE edge3 when GetTyreDashEdge is called with
\               Y = &E7

LDA #0                 \ Overwrite the &AA value with 0 to remove the marker
STA (P),Y

CPY blockOffset        \ If Y <> blockOffset then this can't be our marker, as
BNE edge5              \ the marker is on line blockOffset, so jump back to
\ edge5 to merge this byte with the correct background
\ colour

\ If we get here then we have reached our marker at the
\ bottom of the edge

LDA W                  \ Restore the entry in the dash data block that we
STA (P),Y              \ overwrote with the marker, whose original contents we
\ stored in W

.edge12

RTS                    \ Return from the subroutine

ENDIF
```