.draw11 LDA colourData \ If bit 4 of colourData is clear, jump to draw12 to AND #%00010000 \ keep the edge colour we set at the start of part 1 BEQ draw12 TYA \ If Y = 0, then we are drawing an extra edge, so jump BEQ draw12 \ to draw12 to keep the edge colour we set at the start \ of part 1 \ Otherwise bit 4 of colourData is set and this is a \ left or right edge, which means we use the fill colour \ instead of the edge colour, but only if this is an \ outside edge (i.e. a left edge in the left half of the \ screen, or a right edge in the right half of the \ screen), so the edge is effectively hidden by merging \ it into the object's fill EOR T \ Set A = bit 0 of Y EOR bit 0 of T AND #1 BEQ draw12 \ If A = 0, then one of the following is true: \ \ * Y = 2 (%10) and bit 0 of T = 0, in which case we \ are drawing a right edge in the left half of the \ screen \ \ * Y = 1 (%01) and bit 0 of T = 1, in which case we \ are drawing a left edge in the right half of the \ screen \ \ In either case, jump to draw12 to keep the colour we \ set in edgePixel at the start of part 1, as this is \ not an outside edge \ If we get here then bit 4 of colourData is set, and we \ are drawing a left or right edge as an outside edge, \ so we set the edge colour to the logical colour in \ bits 0-1 of colourData, i.e. the fill colour LDA colourData \ Set X to bits 0-1 of colourData, which contains the AND #%00000011 \ fill colour of the object part we are drawing TAX LDA objectPalette,X \ Set edgePixel to the fill colour, so the edge merges STA edgePixel \ into the object's background .draw12 LDA thisEdge \ Set A to thisEdge, which we set in part 1 to the \ pixel x-coordinate of the edge to draw AND #3 \ Set X = A mod 4, which is the number of the pixel of TAX \ the edge we want to draw within the four-pixel byte \ (i.e. 0 to 3, left to right) LDA yLookupLo+8,X \ Set A to the X-th pixel mask from yLookupLo+8, which \ is a pixel byte with the X-th pixel clear EOR #&FF \ Invert A so it contains a pixel byte with only the \ X-th pixel set AND edgePixel \ Apply the pixel mask to the edge colour in edgePixel, STA edgePixel \ so edgePixel now contains a pixel byte with only the \ X-th pixel set, and that pixel is set to the edge \ colour CPY #1 \ If Y >= 1, then we are drawing a left or right edge, BCS draw16 \ so jump to draw16 \ If we get here then Y = 0, so we are drawing one of \ the extra edges as part of a four-edge object part LDA pixelsToLeft,X \ Set A to 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 AND leftOfEdge \ Set these pixels to leftOfEdge, which is either the STA T \ fill colour of the object (if there is just this edge \ in the pixel byte), or it's the pixel byte with the \ previous edge already drawn (if we have both edges in \ the same byte) \ \ In either case, this fills the pixel byte with the \ correct contents to the left of this edge and stores \ them in T LDA rightOfEdge \ Set A to a pixel byte with the pixels to the right of AND pixelsEdgeRight,X \ the X-th pixel set to rightOfEdge, so this is the same \ thing but with the bytes to the right of the edge ORA T \ OR the two together so we have a pixel byte with the \ correct bytes to the left and right of this edge AND yLookupLo+8,X \ Apply the X-th pixel mask from yLookupLo+8, so this \ clears the X-th pixel in the pixel byte ORA edgePixel \ We set up edgePixel above to contain a single pixel \ for the edge in position X, set to the edge colour, \ so this sets the X-th pixel in A to the edge colour, \ so the pixel byte in A now contains the edge itself STA I \ A now contains a pixel byte with the correct bytes set \ to the left and right of the edge, plus the correct \ colour set for the edge pixel, so store this pixel \ byte in I LDA prevEdgeInByte \ If prevEdgeInByte = 0 then this edge is the first one BEQ draw13 \ in this byte, so jump to draw13 to potentially draw \ this edge using a quick-draw routine that doesn't \ worry about any existing background content (as this \ is always overwritten by the extra parts in the middle \ of the object part) \ If we get here then prevEdgeInByte is non-zero, so \ this pixel byte contains both the previous edge and \ this edge LDA #0 \ Set prevEdgeInByte = 0, to reset it for the next call STA prevEdgeInByte \ to DrawObjectEdge, as we have moved on to the next \ edge since it was made non-zero LDA edgePixelMask \ Set L to the pixel mask for the previous edge, which STA L \ we set in the previous call to DrawObjectEdge to have \ bits set for the pixels to the right of the previous \ edge, so once the extra edges are done we can use it \ when filling the last part of the extra section EOR #&FF \ Set A to the inverse, so it has bits set for the \ pixels of the previous edge and everything to its left AND I \ Insert the pixels from I so the left part of our pixel \ byte is given the correct edge and everything to the \ left JMP draw17 \ Jump to draw17 to draw the edge using this pixel byte .draw13 \ If we get here then we are not sharing this pixel byte \ with the previous edge, so we can use a quick-draw \ routine that doesn't worry about any existing \ background content (as this is an extra edge) LDX blockNumber \ If blockNumber <> nextBlockNumber, then the next edge CPX nextBlockNumber \ isn't in the same dash data block (i.e. in the same BNE draw14 \ column), so jump to draw14 to draw this edge \ Otherwise the next edge is in the same byte as this \ one, so we need to return from the subroutine via \ draw29 (i.e. first check whether we need to fill to \ the left of this edge, and then return) LDA I \ Store the pixel byte in rightOfEdge so the next call STA rightOfEdge \ to DrawObjectEdge can add the next edge to it JMP draw29 \ Jump to draw29 to check whether we need to fill to the \ left of this edge, and then move on to the next edge .draw14 \ We now draw this edge using a quick-draw routine that \ doesn't worry about any existing background content LDA I \ Set A to the pixel byte for the edge we want to draw BNE draw15 \ If the pixel byte is non-zero, jump to draw15 to skip \ the following instruction LDA #&55 \ Set A = &55 to use as the value of WW below (&55 in \ the screen buffer represents colour 0, or black) .draw15 LDY topTrackLine \ Set Y = topTrackLine, which is the number of the \ track line at the top of the object, which is the \ same as the offset into the dash data block for the \ top edge JMP DrawEdge \ Jump to DrawEdge to draw the edge from topTrackLine \ down to blockOffset, which we set in part 2 to the \ bottom track line of the edge we want to draw, and \ rejoin the routine at draw29 for the next edge .draw16 \ If we get here then we are drawing either a left or \ right edge, and Y is 1 or 2 respectively BNE draw18 \ We did a CPY #1 before jumping here, so this jumps to \ draw18 if Y <> 1, i.e. Y = 2, so we jump to draw18 if \ we are drawing a right edge \ If we get here then we are drawing a left edge in \ pixel X within the pixel byte, so we now calculate the \ pixel byte for the left edge LDA pixelsToLeft,X \ Set A to 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 - in other words, with all the pixels \ outside of the object (to the left of the left edge) \ set STA L \ Store this pixel mask in L, so L contains a pixel mask \ containing the pixels to the left of the left edge EOR #&FF \ Invert A so it contains a pixel byte with the X-th \ pixel set, plus all the pixels to the right - in other \ words, with the edge and the inside of the object set AND rightOfEdge \ Set the object pixels to rightOfEdge, which contains \ the fill colour for the object (as at this point we \ won't be sharing a pixel byte with the previous edge, \ as there is no previous edge) AND yLookupLo+8,X \ Apply the X-th pixel mask from yLookupLo+8, so this \ clears the X-th pixel in the pixel byte ORA edgePixel \ We set up edgePixel above to contain a single pixel \ for the edge in position X, set to the edge colour, \ so this sets the X-th pixel in A to the edge colour, \ so the pixel byte in A now contains the edge itself .draw17 \ If we get here then we are either drawing a left edge, \ or this is a four-edge object part and we are sharing \ this pixel byte with the previous edge LDX blockNumber \ If blockNumber <> nextBlockNumber, then the next edge CPX nextBlockNumber \ isn't in the same dash data block (i.e. in the same BNE draw19 \ column) as this one, so jump to draw19 to draw this \ edge \ If we get here then: \ \ * The next edge is in the same pixel byte as the \ edge we are currently drawing, so we don't draw \ this byte yet, but instead return from the routine \ so the next call to DrawObjectEdge can pick up the \ baton and insert the next edge into the byte we \ just created \ \ * The C flag is set, as the above comparison was \ blockNumber = nextBlockNumber STA rightOfEdge \ Set rightOfEdge to the pixel byte in A, ready for \ the next call to DrawObjectEdge to pick it up LDA L \ Set edgePixelMask to the pixel mask in L, which STA edgePixelMask \ contains the pixels to the left of the left edge, to \ pass to the next call to DrawObjectEdge ROR prevEdgeInByte \ Set bit 7 of prevEdgeInByte, so it is non-zero for the \ next call to DrawObjectEdge, to indicate that the next \ edge needs to be inserted into the pixel byte that we \ just built, alongside the current edge RTS \ Return from the subroutine .draw18 \ If we get here then we are drawing a right edge in \ pixel X within the pixel byte, so we now calculate the \ pixel byte for the right edge \ \ This routine draws the right edge in the pixel byte, \ making sure we keep any previous edge that's already \ drawn in the same pixel byte LDA edgePixelMask \ Set A to the edge pixel mask of the previous edge, \ which will: \ \ * Be empty if the previous edge was already drawn \ and we do not need to share this pixel byte with \ the previous edge \ \ * Contain set pixels for the previous edge if both \ this edge and the previous edge need to share the \ same pixel byte ORA pixelsToRight,X \ The pixelsToRight table contains pixel bytes with all \ the pixels set to the right of the X-th pixel, so this \ sets all the pixels to the right of the X-th pixel \ A now contains a pixel byte with pixels set to the \ right of this edge, and if the previous edge is in the \ same byte, pixels are also set to the left of that \ edge STA L \ Store this pixel mask in L so we can use it in part 4, \ so L contains a pixel mask containing the pixels to \ the right of the right edge (and the left of the \ previous edge, if it's in the same byte) EOR #&FF \ Invert A so it contains the pixels of this edge, plus \ the previous edge if this was drawn in the same byte AND leftOfEdge \ Set these pixels to leftOfEdge, which is either the \ fill colour of the object (if there is just this edge \ in the pixel byte), or it's the pixel byte of the \ previous edge (if we have both edges in the same byte) \ \ In either case, this fills the pixel byte with the \ correct contents AND yLookupLo+8,X \ Apply the X-th pixel mask from yLookupLo+8, so this \ clears the X-th pixel in the pixel byte ORA edgePixel \ We set up edgePixel above to contain a single pixel \ for the edge in position X, set to the edge colour, \ so this sets the X-th pixel in A to the edge colour, \ so the pixel byte in A now contains the edge itself \ So we now have a pixel byte in A that contains this \ edge in the correct colour, and if this pixel byte \ also contains the previous edge, that's in there tooName: DrawObjectEdge (Part 3 of 5) [Show more] Type: Subroutine Category: Drawing objects Summary: Construct a pixel byte for the edge we want to draw Deep dive: Creating objects from edgesContext: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

[X]

Subroutine DrawEdge (category: Drawing objects)

Draw an edge, overwriting whatever is already on-screen

[X]

Variable blockNumber in workspace Zero page

The dash data block number for the current edge

[X]

Variable colourData in workspace Zero page

Colour data for the current object part

[X]

Label draw12 is local to this routine

[X]

Label draw13 is local to this routine

[X]

Label draw14 is local to this routine

[X]

Label draw15 is local to this routine

[X]

Label draw16 is local to this routine

[X]

Label draw17 is local to this routine

[X]

Label draw18 is local to this routine

[X]

Label draw19 in subroutine DrawObjectEdge (Part 4 of 5)

[X]

Entry point draw29 in subroutine DrawObjectEdge (Part 5 of 5) (category: Drawing objects)

Fill the inside of the object part from the previous block to the current one

[X]

Variable edgePixelMask in workspace Zero page

The pixel mask for the previous edge

[X]

Variable leftOfEdge in workspace Zero page

The fill colour to the left of the edge we are drawing

[X]

Variable nextBlockNumber in workspace Zero page

The dash data block number for the next edge

[X]

Variable objectPalette (category: 3D objects)

The object colour palette that maps logical colours 0 to 3 to physical colours

[X]

Variable pixelsEdgeRight (category: Drawing pixels)

Pixel byte with all the pixels to the right of position X set, plus pixel X

[X]

Variable pixelsToLeft (category: Drawing pixels)

Pixel byte with all the pixels to the left of position X set

[X]

Variable pixelsToRight (category: Drawing pixels)

Pixel byte with all the pixels to the right of position X set

[X]

Variable prevEdgeInByte in workspace Zero page

Determines whether we are drawing two edges within the same pixel byte in DrawObjectEdge

[X]

Variable rightOfEdge in workspace Zero page

The fill colour to the right of the edge we are drawing

[X]

Variable topTrackLine in workspace Zero page

The top track line for the current object part

[X]

Variable yLookupLo (category: Drawing pixels)

Lookup table for converting pixel y-coordinate to low byte of screen address