Skip to navigation

Revs on the BBC Micro

Drawing the track: DrawVergeByteLeft

Name: DrawVergeByteLeft [Show more] Type: Subroutine Category: Drawing the track Summary: Draw two bytes into the screen buffer in the first and second dash data blocks for the edge Deep dive: Drawing the track verges
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawShallowToLeft calls DrawVergeByteLeft * DrawShallowToRight calls DrawVergeByteLeft * DrawSteepToLeft calls DrawVergeByteLeft * DrawSteepToRight calls DrawVergeByteLeft

This routine draws a single byte of a verge edge in the first dash data block of the three that we set up in DrawSegmentEdge. It also draws a second byte to the right, in the second dash data block, using the fill colour so the screen gets filled to the right of the verge edge.
Arguments: X The pixel number of the edge within the pixel byte, with 0 being the first pixel (at the left end of the byte) to 3 as the last pixel (at the right end of the byte) Y The track line to draw on (0 to 79) RR The pitch angle of the current segment (we stop drawing the edge when Y reaches this value) UU The number of the dash data block where we start drawing JJ The right pixel byte when drawing the edge in the screen buffer, i.e. the fill byte to the right of the edge (S R) Address of the first dash data block in the memory page containing the pixels at the start of the previous edge (Q P) Address of the second dash data block in the memory page containing the pixels at the start of the previous edge
Returns: C flag The C flag is cleared Y Incremented or decremented, depending on which way the verge goes (decremented if the verge goes down, incremented is it goes up) A A is unchanged
.DrawVergeByteLeft STA II \ Store A in II so we can retrieve it later .verl1 NOP \ This instruction is modified by the DrawSegmentEdge \ routine, to be NOP, INY or DEY, to move on to the next \ track line as appropriate CPY RR \ If Y = RR, we have reached the pitch angle of the BEQ StopDrawingEdge \ current edge, so jump to StopDrawingEdge to stop \ drawing the edge LDA UU \ Set A = UU, the number of the dash data block where we \ want to draw .verl2 STA &7000,Y \ This instruction is modified by the DrawVergeEdge \ routine to point to the relevant table for the edge \ we are drawing: \ \ * leftVergeStart \ \ * leftTrackStart \ \ * rightVergeStart \ \ * rightGrassStart \ \ So this stores the dash data block number for the \ previous edge in the relevant verge table for track \ line Y LDA (R),Y \ Set A to the current contents of track line Y in \ (S R), which is the dash data block containing the \ previous edge BNE verl6 \ If the current contents of the screen buffer is \ non-zero, then it already contains something, so jump \ to verl6 to merge our edge with the existing pixels LDA objectPalette,X \ Set A to the X-th entry from the object palette, which \ contains a background colour byte with the first X \ pixels in the foreground colour .verl3 STA (R),Y \ Store the pixel byte in the dash data block LDA JJ \ Store the pixel byte in JJ in the next dash data block STA (P),Y \ to fill the pixel byte to the right of the edge byte \ with the background colour in JJ (so this fills to the \ right of the edge as we draw it) .verl4 LDA II \ Retrieve the value of A we stored above, so A is \ unchanged by the routine .verl5 INY \ This instruction is modified by the DrawSegmentEdge \ routine, to be NOP, INY or DEY, to move on to the next \ track line as appropriate CLC \ Clear the C flag RTS \ Return from the subroutine .verl6 \ If we get here then the pixel byte we are drawing into \ is non-empty CPY #44 \ If Y >= 44, jump to verl7 to skip the following check, BCS verl7 \ as offsets of 44 and above are always within a dash \ data block JSR CheckDashData \ Check whether offset Y points to dash data within \ block UU, clearing the C flag if it does BCC verl4 \ If offset Y does not point to dash data, jump to verl4 \ to return from the subroutine without drawing anything .verl7 \ If we get here then the pixel byte we are drawing into \ is non-empty and is a valid part of the screen buffer CMP #&55 \ If the current contents of the screen buffer is not BNE verl8 \ &55, then it does not denote black, so skip the \ following LDA #0 \ The current contents of the screen buffer is &55, \ which denotes black, so set A to 0 so we merge with a \ pixel byte of black .verl8 AND pixelsToLeft,X \ AND the current contents with the X-th pixel mask from \ pixelsToLeft, which is a pixel byte with all the \ pixels set to the left of the X-th pixel, so this \ clears all pixels in the existing screen buffer byte \ from the X-th pixel and to the right \ \ In other words, this clears the track edge and to the \ right, but keeps content to the left of the edge ORA vergeEdgeRight,X \ We set up vergeEdgeRight to contain the pixel bytes \ from objectPalette, but masked to only include the \ rightmost 4, 3, 2 and 1 pixels, so this inserts the \ edge and all the pixels to the right of the edge into \ the pixels that we just cleared, thus drawing the edge \ on top of what's already on-screen BNE verl3 \ If the resulting pixel byte in A is non-zero, then we \ are ready to poke it into the screen buffer, so jump \ to verl3 LDA #&55 \ The resulting pixel byte is zero, which is a black \ pixel byte, and we represent this in the screen buffer \ with &55, so set A to &55 so we poke this into the \ screen buffer instead of zero BNE verl3 \ Jump to verl3 (this BNE is effectively a JMP as A is \ never zero)