Plot at and pixel position, clipped to the graphics window - 438 bytes (2.6%)
.plotSprite = $a258 LDY #.workspaceOffsetCurrentSpriteAddressLow } LDA (.privateWorkspaceLow),Y } get current sprite address INY } ORA (.privateWorkspaceLow),Y } BNE .plotSpriteInternal if (we have a sprite address) then branch JMP .setGraphicsCursorPositionAndFinishPLOT .plotSpriteInternal = $a264 LDA (.privateWorkspaceLow),Y TAX X = sprite address high DEY LDA (.privateWorkspaceLow),Y A = sprite address low STA .privateWorkspaceLow } make .privateWorkspace point STX .privateWorkspaceHigh } to current sprite Copy sprite header to workspace (for easier access) LDY #5 loop counter - LDA (.privateWorkspaceLow),Y } STA .vduWorkspaceA,Y } copy sprite header DEY } to .vduWorkspaceA BPL - } .vduWorkspaceCD = length of sprite data (including 6 byte header) CLC } LDA .privateWorkspaceLow } ADC #6 } STA .vduWorkspaceC } .vduWorkspaceCD = sprite size LDA .privateWorkspaceHigh } (including header) ADC #0 } STA .vduWorkspaceD } Reset .vduWorkspaceEFGH, .vduWorkspaceIJ (sprite width), and .vduWorkspaceKL (sprite height) to zero LDY #7 loop counter LDA #0 - STA .vduWorkspaceE,Y DEY BPL - LDA .vduWorkspaceA sprite width STA .vduWorkspaceI .vduWorkspaceI = sprite width-1 (in bytes) LDA .vduWorkspaceB sprite height STA .vduWorkspaceK .vduWorkspaceK = sprite height-1 (in pixels) .vduWorkspaceIJ = ((width in bytes-1) * pixels per byte) + (pixels per byte - 1) = width in pixels - 1 LDA .vduPixelsPerByteMinusOne loop counter - ASL .vduWorkspaceI IJ *= 2 ROL .vduWorkspaceJ LSR loop counter divided by 2 BNE - Add the number of pixels per byte minus one LDA .vduPixelsPerByteMinusOne ORA .vduWorkspaceI STA .vduWorkspaceI I = I OR pixels per byte .vduWorkspaceMNOP = PLOT parameter LDX #.vdu25ParameterXLow - .vduVariablesStart source LDY #.vduWorkspaceM - .vduVariablesStart destination JSR .copyFourBytesWithinVDUVariables copy: .vduWorkspaceMNOP = Parameter point STY .vduTempStoreDA Store Y=.vduWorkspaceQ - .vduVariablesStart Mask off fractional pixel amounts from X coordinate LDA .vduPixelsPerByteMinusOne EOR #$FF AND .vduWorkspaceM STA .vduWorkspaceM .vduWorkspaceQRST = .vduWorkspaceIJKL + .vduWorkspaceMNOP - .vduWorkspaceEFGH = (width-1,height-1) + PLOT point - zero = top right corner of sprite LDX #.vduWorkspaceM - .vduVariablesStart PLOT point LDY #.vduWorkspaceI - .vduVariablesStart sprite (width-1, height-1) LDA #.vduWorkspaceE - .vduVariablesStart zero JSR .calculatePointVduYPlusVduXMinusVduA Check if point .vduWorkspaceMNOP (bottom left of sprite) is within the graphics window LDX #.vduWorkspaceM - .vduVariablesStart JSR .checkPointXIsWithinGraphicsWindow %0000 success (gpoint is within window) %0001 gpoint X is left of the left edge of the graphics window %0010 gpoint X is right of the right edge of the graphics window %0100 gpoint Y is below the bottom edge of the graphics window %1000 gpoint Y is above the top edge of the graphics window BEQ .plotSpriteAfterClippingBottomLeft if (within the graphics window) then branch AND #%1010 look to see if above or right BEQ .clipSpriteBottomLeft if (to the left or below the graphics window) then branch Destination is outside of the graphics window (to the right or above) so nothing will get drawn. Finish up. .finishUp = $a2da JMP .setGraphicsCursorPositionAndFinishPLOT .clipSpriteBottomLeft = $a2dd LDA .vduTempStoreDA check result of graphics window boundary check PHA remember it AND #%0001 BEQ .doneLeftClip if (not left of the graphics window) then branch Clip sprite to left edge of graphics window LDX #.vduGraphicsWindowPixelsLeftLow - .vduVariablesStart LDY #.vduWorkspaceE - .vduVariablesStart STY .vduTempStoreDA LDA #.vduWorkspaceM - .vduVariablesStart JSR .calculateCoordinateVduYPlusVduXMinusVduA LDY #.vduWorkspaceM - .vduVariablesStart STY .vduTempStoreDA JSR .calculateCoordinateVduYPlusVduXMinusVduA .doneLeftClip = $a2f6 PLA check result of graphics window boundary check AND #%0100 check if below BEQ .plotSpriteAfterClippingBottomLeft if (not below the graphics window) then branch Clip sprite to bottom edge of graphics window LDX #.vduGraphicsWindowPixelsBottomLow - .vduVariablesStart LDY #.vduWorkspaceG - .vduVariablesStart STY .vduTempStoreDA LDA #.vduWorkspaceO - .vduVariablesStart JSR .calculateCoordinateVduYPlusVduXMinusVduA LDY #.vduWorkspaceO - .vduVariablesStart STY .vduTempStoreDA JSR .calculateCoordinateVduYPlusVduXMinusVduA .plotSpriteAfterClippingBottomLeft = $a30d Check if point .vduWorkspaceQRST (top right corner of sprite) is within graphics window LDX #.vduWorkspaceQ - .vduVariablesStart JSR .checkPointXIsWithinGraphicsWindow %0000 success (gpoint is within window) %0001 gpoint X is left of the left edge of the graphics window %0010 gpoint X is right of the right edge of the graphics window %0100 gpoint Y is below the bottom edge of the graphics window %1000 gpoint Y is above the top edge of the graphics window BEQ .plotSpriteAfterClippingTopRight if (within graphics window) then branch AND #%0101 BNE .finishUp if (below or left of the graphics window) then branch (finish up) LDA .vduTempStoreDA check result of graphics window boundary check PHA remember it AND #%0010 BEQ .doneRightClip if (not right of the graphics window) then branch Clip sprite to right edge of graphics window LDX #.vduGraphicsWindowPixelsRightLow - .vduVariablesStart LDY #.vduWorkspaceI - .vduVariablesStart STY .vduTempStoreDA LDA #.vduWorkspaceQ - .vduVariablesStart JSR .calculateCoordinateVduYPlusVduXMinusVduA LDY #.vduWorkspaceQ - .vduVariablesStart STY .vduTempStoreDA JSR .calculateCoordinateVduYPlusVduXMinusVduA .doneRightClip = $a331 PLA AND #%1000 BEQ .plotSpriteAfterClippingTopRight if (not above the graphics window) then branch Clip sprite to the top of the graphics window LDX #.vduGraphicsWindowPixelsTopLow - .vduVariablesStart LDY #.vduWorkspaceK - .vduVariablesStart STY .vduTempStoreDA LDA #.vduWorkspaceS - .vduVariablesStart JSR .calculateCoordinateVduYPlusVduXMinusVduA LDY #.vduWorkspaceS - .vduVariablesStart STY .vduTempStoreDA JSR .calculateCoordinateVduYPlusVduXMinusVduA .plotSpriteAfterClippingTopRight = $a348 All clipping is done Divide X pixel coordinates to get byte coordinates again LDA .vduPixelsPerByteMinusOne .getByteCoordinates = $a34b LSR .vduWorkspaceJ ROR .vduWorkspaceI LSR .vduWorkspaceF ROR .vduWorkspaceE LSR BNE .getByteCoordinates Set screen address for .vduWorkspaceQRST (top right corner of sprite) LDX #.vduWorkspaceQ - .vduVariablesStart JSR .setScreenAddress SEC LDA .vduWorkspaceB SBC .vduWorkspaceK TAX X=loop counter BEQ .skipAddingSpriteWidths .addWidthToSpriteAddressLoop = $a369 .vduWorkspaceCD += .vduWorkspaceA SEC LDA .vduWorkspaceC ADC .vduWorkspaceA STA .vduWorkspaceC BCC + INC .vduWorkspaceD + DEX loop counter BNE .addWidthToSpriteAddressLoop .skipAddingSpriteWidths = $a37b .vduWorkspaceCD += .vduWorkspaceA - .vduWorkspaceI SEC LDA .vduWorkspaceA SBC .vduWorkspaceI CLC ADC .vduWorkspaceC STA .vduWorkspaceC BCC + INC .vduWorkspaceD + .vduWorkspaceG = .vduWorkspaceK - .vduWorkspaceG SEC LDA .vduWorkspaceK SBC .vduWorkspaceG STA .vduWorkspaceG .vduWorkspaceG += 1 INC .vduWorkspaceG .vduWorkspaceE = .vduWorkspaceI - .vduWorkspaceE SEC LDA .vduWorkspaceI SBC .vduWorkspaceE STA .vduWorkspaceE .vduWorkspaceE += 1 INC .vduWorkspaceE .plotSpriteLoop = $a3a8 LDA .vduScreenAddressOfGraphicsCursorCellLow } PHA } LDA .vduScreenAddressOfGraphicsCursorCellHigh } remember screen address PHA } at the start of the row LDA .vduWorkspaceC } STA .privateWorkspaceLow } LDA .vduWorkspaceD } set row start of sprite data } address STA .privateWorkspaceHigh } LDX .vduWorkspaceE loop counter .plotSpriteRowLoop = $a3bb LDY #0 LDA (.privateWorkspaceLow),Y read sprite byte PHA ORA .gcolModeMask2 } EOR .gcolModeMask3 } STA .vduGraphicsColourByteEOR } apply GCOL mode PLA } ORA .gcolModeMask0 } EOR .gcolModeMask1 } LDY .vduGraphicsCursorVerticalOffsetInCell } write byte to screen !if (MACHINE = BBC_B) | (MACHINE = ELECTRON) { ORA (.vduScreenAddressOfGraphicsCursorCellLow),Y } EOR .vduGraphicsColourByteEOR } STA (.vduScreenAddressOfGraphicsCursorCellLow),Y write byte to screen } else if MACHINE = BBC_B_PLUS { STA .vduGraphicsColourByteOR JSR .plotByte write byte to screen with GCOL mode } else { +unknown_machine } INC .privateWorkspaceLow } BNE + } increment workspace pointer INC .privateWorkspaceHigh } + } SEC JSR .moveGraphicsCursorAddressTotheLeftAndUpdateMask DEX BNE .plotSpriteRowLoop if (not done) then branch (loop back) PLA } STA .vduScreenAddressOfGraphicsCursorCellHigh } restore original screen address PLA } STA .vduScreenAddressOfGraphicsCursorCellLow } .vduWorkspaceCD += sprite width SEC LDA .vduWorkspaceC ADC .vduWorkspaceA STA .vduWorkspaceC BCC + INC .vduWorkspaceD + Increment offset within cell INC .vduGraphicsCursorVerticalOffsetInCell LDY .vduGraphicsCursorVerticalOffsetInCell CPY #8 BCC + if (not the bottom of the cell) then branch JSR .plotSpriteMoveDownOneCell move down to next cell STY .vduGraphicsCursorVerticalOffsetInCell + Decrement number of rows left to plot DEC .vduWorkspaceG BNE .plotSpriteLoop if (not done yet) then branch (loop back) JMP .setGraphicsCursorPositionAndFinishPLOT