*SGET; *SSAVE; *SLOAD; *SMERGE; *SCHOOSE; *SRENUMBER - 1018 bytes (6.2%)


§1. *SGET n.

 Executes 'VDU 23,27,1,n,0,0,0,0,0,0' to capture a rectangle of the screen to sprite n

 On Entry:
   XY: address of the rest of the command line
.starSGet = $a40e
    JSR .read8BitNumberIntoA                            

    PHA                                                 
    JSR .printInlineCounted                             display following message
    !byte 3                                             length of message to print
    !text 23,27,1                                       get sprite from screen

    PLA                                                 
    JSR .OSWRCH                                         sprite to get

    JSR .printInlineCounted                             display following message
    !byte 6                                             length of message to print
    !text 0,0,0,0,0,0                                   finish VDU stream

    RTS                                                 

§2. noSpriteMemoryErrorLocal.

.noSpriteMemoryErrorLocal = $a428
    JMP .noSpriteMemoryError                            

§3. sgetRectOutOfBounds.

.sgetRectOutOfBounds = $a42b
    PLA                                                 
    RTS                                                 

§4. sgetInternal.

.sgetInternal = $a42d
    PHA                                                 
    LDY #.workspaceOffsetSpritePages                    
    LDA (.privateWorkspaceLow),Y                        
    BEQ .noSpriteMemoryErrorLocal                       

    Sort current graphics cursor and old graphics cursor points
    LDX #.vduOldGraphicsCursorPixelsXLow - .vduVariablesStart 
    JSR .sortCoordinatesAsBottomLeftAndTopRight         set .vduWorkspaceAB,CD to bottom
                                                        left point,
                                                        and .vduWorkspaceEF,GH to top right

    LDX #.vduWorkspaceA - .vduVariablesStart            
    JSR .checkPointXIsWithinGraphicsWindow              
    BEQ .sgetBottomLeftPointWithinBounds                

    AND #%00001010                                      
    BNE .sgetRectOutOfBounds                            if (bottom left point of rectangle
                                                        is right or above graphics window)
                                                        then branch (exit)

    LDA .vduTempStoreDA                                 
    PHA                                                 
    AND #1                                              
    BEQ +                                               if (bottom left point of rect is
                                                        not left of graphics window) then
                                                        branch

    LDX #.vduGraphicsWindowPixelsLeftLow - .vduVariablesStart } copy left edge of graphics
    LDY #.vduWorkspaceA - .vduVariablesStart            } window into current workspace
                                                        } position
    JSR .copyTwoBytesWithinVDUVariables                 } i.e. clip to left edge

+
    PLA                                                 
    AND #4                                              
    BEQ .sgetBottomLeftPointWithinBounds                if (bottom left point is not
                                                        below the graphics window) then
                                                        branch

    LDX #.vduGraphicsWindowPixelsBottomLow - .vduVariablesStart } copy bottom edge of
                                                                } graphics
    LDY #.vduWorkspaceC - .vduVariablesStart            } window into current workspace
                                                        } position
    JSR .copyTwoBytesWithinVDUVariables                 } i.e. clip to bottom edge

.sgetBottomLeftPointWithinBounds = $a45e
    LDX #.vduWorkspaceE - .vduVariablesStart            
    JSR .checkPointXIsWithinGraphicsWindow              
    BEQ .sgetAllWithinBounds                            if (top right point is in bounds)

    AND #5                                              
    BNE .sgetRectOutOfBounds                            if (top right point of rectangle
                                                        is left or below graphics window)
                                                        then branch

    LDA .vduTempStoreDA                                 
    PHA                                                 
    AND #2                                              
    BEQ +                                               if (top right point of rect is not
                                                        right of the graphics window) then
                                                        branch

    LDX #.vduGraphicsWindowPixelsRightLow - .vduVariablesStart } copy right edge of graphics
    LDY #.vduWorkspaceE - .vduVariablesStart            } window into current workspace
                                                        } position
    JSR .copyTwoBytesWithinVDUVariables                 } i.e. clip to right edge

+
    PLA                                                 
    AND #8                                              
    BEQ .sgetAllWithinBounds                            if (top right point of rect is not
                                                        above the graphics window) then
                                                        branch

    LDX #.vduGraphicsWindowPixelsTopLow  - .vduVariablesStart } copy top edge of graphics
    LDY #.vduWorkspaceG - .vduVariablesStart            } window into current workspace
                                                        } position
    JSR .copyTwoBytesWithinVDUVariables                 } i.e. clip to top edge

.sgetAllWithinBounds = $a483
    LDX #.vduWorkspaceE - .vduVariablesStart            
    JSR .setScreenAddress                               set screen address based on top right
                                                        point of rectangle

    .vduWorkspaceAB = width of rect
    SEC                                                 }
    LDA .vduWorkspaceE                                  }
    SBC .vduWorkspaceA                                  }
    STA .vduWorkspaceA                                  } AB = EF - AB = width of rect
    LDA .vduWorkspaceF                                  }
    SBC .vduWorkspaceB                                  }
    STA .vduWorkspaceB                                  }

    Loop to convert AB into a byte width rather than width in pixels
    LDA .vduPixelsPerByteMinusOne                       
-
    LSR .vduWorkspaceB                                  
    ROR .vduWorkspaceA                                  .vduWorkspaceAB /= 2
    LSR                                                 
    BNE -                                               

    At this point .vduWorkspaceB is zero, because our sprite is less than 256 pixels wide.
    We reuse .vduWorkspaceB below.

    Calculate the width and height of the sprite we are going to create
    
    X=A+1         width of sprite
    B=G-C
    Y=G-C+1       height of sprite
    If Y=0 Y=255:B-=1
    LDX .vduWorkspaceA                                  
    INX                                                 X = .vduWorkspaceA + 1
    SEC                                                 
    LDA .vduWorkspaceG                                  }
    SBC .vduWorkspaceC                                  } B = G - C
    STA .vduWorkspaceB                                  }
    TAY                                                 
    INY                                                 
    BNE +                                               
    DEY                                                 
    DEC .vduWorkspaceB                                  
+
    Calculate width * height to see how much memory we need
    JSR .multiply8x8                                    DE/F = X*Y

    Store result in .vduWorkspaceCD
    CLC                                                 [NOTE: redundant, CLC not used]
    LDA .vduTempStoreDE                                 
    STA .vduWorkspaceC                                  
    LDA .vduTempStoreDF                                 
    STA .vduWorkspaceD                                  

    JSR .getFreeSpace                                   

    Now .vduTempStoreDE/DF holds the free space in bytes

    PLA                                                 
    PHA                                                 
    JSR .findSpriteA                                    
    BEQ .skipExistingSprite                             

    Add size of existing sprite to free space
    CLC                                                 
    LDY #.spriteHeaderOffsetSizeInBytesLow              
    LDA (.vduTempStoreDC),Y                             
    ADC .vduTempStoreDE                                 
    STA .vduTempStoreDE                                 
    INY                                                 Y =
                                                        .spriteHeaderOffsetSizeInBytesHigh
    LDA (.vduTempStoreDC),Y                             
    ADC .vduTempStoreDF                                 
    STA .vduTempStoreDF                                 

    Add 6 to free space (for the old sprite header data)
    LDA #6                                              }
    ADC .vduTempStoreDE                                 }
    STA .vduTempStoreDE                                 } [NOTE: don't add six only to
                                                        } subtract it again, just skip
                                                        } forward, i.e.: JMP +]
    BCC .skipExistingSprite                             }
    INC .vduTempStoreDF                                 }

.skipExistingSprite = $a4ef
    Subtract 6 from the free space (for the new sprite header data)
    SEC                                                 
    LDA .vduTempStoreDE                                 
    SBC #6                                              
    BCS +                                               
    DEC .vduTempStoreDF                                 
+

    Check we have enough room for the new sprite
    if (free space >= size of new sprite)
    CMP .vduWorkspaceC                                  
    LDA .vduTempStoreDF                                 
    SBC .vduWorkspaceD                                  
    BMI .noRoomToGetSpriteError                         

    Delete the existing sprite
    PLA                                                 
    PHA                                                 
    JSR .deleteSpriteInternal                           

    tempStoreDC/D = DA/B = start of sprite data
    DA/B += 6 for the sprite header data
    CLC                                                 
    LDA .vduTempStoreDA                                 
    STA .vduTempStoreDC                                 
    ADC #6                                              
    STA .vduTempStoreDA                                 
    LDA .vduTempStoreDB                                 
    STA .vduTempStoreDD                                 
    BCC +                                               
    INC .vduTempStoreDB                                 
+

    Store sprite number
    LDY #.spriteHeaderOffsetSpriteNumber                
    PLA                                                 
    PHA                                                 
    STA (.vduTempStoreDC),Y                             

    Store current mode
    DEY                                                 Y=.spriteHeaderOffsetModeNumber
    LDA .vduCurrentScreenMODE                           
    STA (.vduTempStoreDC),Y                             

    Store width and height (4 bytes)
    DEY                                                 
.sgetStoreWidthAndHeight = $a525
    LDA .vduWorkspaceA,Y                                
    STA (.vduTempStoreDC),Y                             
    DEY                                                 
    BPL .sgetStoreWidthAndHeight                        

    INC .vduWorkspaceA                                  width
    INC .vduWorkspaceB                                  height (loop counter)

    Loop over each row
.sgetLoopOverRows = $a533
    LDX .vduWorkspaceA                                  width

    Remember current screen address
    LDA .vduScreenAddressOfGraphicsCursorCellLow        
    PHA                                                 
    LDA .vduScreenAddressOfGraphicsCursorCellHigh       
    PHA                                                 

.sgetLoopOverBytesInRow = $a53c
    LDY .vduGraphicsCursorVerticalOffsetInCell          

    A=byte from screen
!if (MACHINE = BBC_B) | (MACHINE = ELECTRON) {
    LDA (.vduScreenAddressOfGraphicsCursorCellLow),Y    read direct from screen memory
} else if MACHINE = BBC_B_PLUS {
    LDA .vduTempStoreDA                                 stash value at $DA which subroutine
                                                        call will corrupt
    PHA                                                 store on stack
    JSR .checkPixelIsBackgroundColourFast               read byte from screen
    EOR .vduBackgroundGraphicsColour                    undo the unwanted eor from
                                                        subroutine call

    TAY                                                 }
    PLA                                                 } restore $DA, preserving A
    STA .vduTempStoreDA                                 }
    TYA                                                 }
} else {
    +unknown_machine
}

    LDY #0                                              
    STA (.vduTempStoreDA),Y                             store byte

    Move sprite address on one byte
    INC .vduTempStoreDA                                 
    BNE +                                               
    INC .vduTempStoreDB                                 
+

    Call OS routine to move graphics cursor left
    SEC                                                 
    JSR .moveGraphicsCursorAddressTotheLeftAndUpdateMask 

    DEX                                                 byte width-=1
    BNE .sgetLoopOverBytesInRow                         

    Restore the screen address
    PLA                                                 
    STA .vduScreenAddressOfGraphicsCursorCellHigh       
    PLA                                                 
    STA .vduScreenAddressOfGraphicsCursorCellLow        

    Move graphics cursor down one row
    INC .vduGraphicsCursorVerticalOffsetInCell          
    LDY .vduGraphicsCursorVerticalOffsetInCell          
    CPY #8                                              
    BCC +                                               
    JSR .plotSpriteMoveDownOneCell                      
    STY .vduGraphicsCursorVerticalOffsetInCell          
+
    DEC .vduWorkspaceB                                  reduce loop counter
    BNE .sgetLoopOverRows                               

    JSR .addSprite                                      add the sprite

    PLA                                                 
    JMP .starSChooseInternal                            choose the new sprite

§5. noRoomToGetSpriteError.

.noRoomToGetSpriteError = $a574
    JSR .generateError                                  
    !byte $82                                           error number
    !text "No room to get sprite",0                     error message

§6. noSpritesError.

.noSpritesError = $a58e
    JSR .generateError                                  
    !byte $83                                           error number
    !text "No Sprites",0                                error message

§7. *SSAVE.

 On Entry:
   XY is the rest of the command line
.starSSave = $a59d
    JSR .prepareFilingSystem                            

    Store address of filename
    TYA                                                 
    LDY #.workspaceOffsetFilenameHigh                   
    STA (.privateWorkspaceLow),Y                        
    TXA                                                 
    DEY                                                 Y = .workspaceOffsetFilenameLow
    STA (.privateWorkspaceLow),Y                        

    Check we have at least one sprite
    LDY #.workspaceOffsetNumberOfSprites                
    LDA (.privateWorkspaceLow),Y                        
    BEQ .noSpritesError                                 if (no sprites) then branch (error)

    JSR .getFreeSpace                                   .vduTempStoreDE/DF = free space in
                                                        bytes

    vduTempStoreDA/B = start of sprite memory
    LDY #.workspaceOffsetSpriteStartPage                
    LDA (.privateWorkspaceLow),Y                        
    STA .vduTempStoreDB                                 
    LDA #0                                              
    STA .vduTempStoreDA                                 

    Store number of sprites
    LDY #.workspaceOffsetNumberOfSprites                }
    LDA (.privateWorkspaceLow),Y                        } get number of sprites
    LDY #2                                              
    STA (.vduTempStoreDA),Y                             store number of sprites

    Store length of sprite data
    LDY #0                                              
    SEC                                                 
    LDA .vduTempStoreDC                                 
    STA (.vduTempStoreDA),Y                             
    INY                                                 
    LDA .vduTempStoreDD                                 
    SBC .vduTempStoreDB                                 subtract start of sprite memory
    STA (.vduTempStoreDA),Y                             

    Store $FF in the two high bytes of start address and all of the end address.
    i.e. six bytes from .workspaceOffsetStartAddressMid2
    LDY #.workspaceOffsetStartAddressMid2 + 5           offset from sart of private workspace
    LDX #6                                              
    LDA #$FF                                            
-
    STA (.privateWorkspaceLow),Y                        
    DEY                                                 
    DEX                                                 
    BNE -                                               

    Store start address (lower two bytes)
    LDY #.workspaceOffsetStartAddressLow                
    LDA #0                                              low byte zero
    STA (.privateWorkspaceLow),Y                        
    INY                                                 
    LDA .vduTempStoreDB                                 high byte of start of workspace
                                                        memory
    STA (.privateWorkspaceLow),Y                        

    Store end address (2 bytes more than start)
    LDY #.workspaceOffsetEndAddressMid1                 
    STA (.privateWorkspaceLow),Y                        high byte of start of workspace
                                                        memory
    DEY                                                 
    LDA #2                                              low byte of start of workspace
                                                        memory (two).
    STA (.privateWorkspaceLow),Y                        

    LDX #.workspaceOffsetParamBlock                     }
    LDY .privateWorkspaceHigh                           }
    LDA #0                                              } Save two byte file?
    JSR .OSFILE                                         }


    JSR .getPrivateWorkspaceAddress                     .privateWorkspaceLow/High = private
                                                        workspace address
    JSR .getFreeSpace                                   .vduTempStoreDE/DF = free space in
                                                        bytes

    vduTempStoreDA/B = start of sprite memory
    LDY #.workspaceOffsetSpriteStartPage                
    LDA (.privateWorkspaceLow),Y                        
    STA .vduTempStoreDB                                 
    LDA #0                                              
    STA .vduTempStoreDA                                 

    Store $FF in two high bytes of start address and all of end address.
    i.e. six bytes from .workspaceOffsetStartAddressMid2
    LDY #.workspaceOffsetStartAddressMid2+5             [NOTE: duplicate of above, could be
                                                        a function instead to save bytes]
    LDX #6                                              
    LDA #$FF                                            
-
    STA (.privateWorkspaceLow),Y                        
    DEY                                                 
    DEX                                                 
    BNE -                                               

    Store start address (start of sprite memory)
    LDY #.workspaceOffsetStartAddressLow                
    LDA .vduTempStoreDA                                 
    STA (.privateWorkspaceLow),Y                        
    INY                                                 Y=$5E
    LDA .vduTempStoreDB                                 
    LDY #.workspaceOffsetStartAddressMid1               [NOTE: Redundant: Y is already set
                                                        to $5E]
    STA (.privateWorkspaceLow),Y                        

    Store end address
    LDY #.workspaceOffsetEndAddressLow                  
    LDA .vduTempStoreDC                                 
    STA (.privateWorkspaceLow),Y                        
    INY                                                 Y = .workspaceOffsetEndAddressMid1
    LDA .vduTempStoreDD                                 
    STA (.privateWorkspaceLow),Y                        

    LDX #.workspaceOffsetParamBlock                     }
    LDY .privateWorkspaceHigh                           }
    LDA #0                                              } Save file proper
    JMP .OSFILE                                         }

§8. *SLOAD.

 On Entry:
   XY is the rest of the command line
.starSLoad = $a638
    JSR .prepareFilingSystem                            

    STX .vduTempStoreDA                                 store filename address
    STY .vduTempStoreDB                                 

    vduTempStoreDC/D = start of sprite data
    LDY #.workspaceOffsetSpriteStartPage                
    LDA (.privateWorkspaceLow),Y                        
    STA .vduTempStoreDD                                 
    LDA #0                                              
    STA .vduTempStoreDC                                 

    JSR .readSpriteFile                                 
    BCS +                                               if (failed to load) then branch

    LDY #.workspaceOffsetNumberOfSprites                }
    STA (.privateWorkspaceLow),Y                        } store number of sprites
    JMP .resetCurrentSpriteAddress                      

+
    RTS                                                 

§9. *SMERGE.

 On Entry:
   XY is the rest of the command line
.starSMerge = $a656
    JSR .prepareFilingSystem                            

    STX .vduTempStoreDA                                 
    STY .vduTempStoreDB                                 store filename address

    JSR .getFreeSpace                                   

    JSR .readSpriteFile                                 
    BCS .return15                                       if (error reading file) then branch

    TAX                                                 X = number of sprites

    vduTempStoreDC/D += 3 (add 3 to sprite address)
    CLC                                                 
    LDA .vduTempStoreDC                                 
    ADC #3                                              
    STA .vduTempStoreDC                                 
    BCC .addSpriteLoop                                  
    INC .vduTempStoreDD                                 

    Add each sprite
.addSpriteLoop = $a671
    TXA                                                 
    PHA                                                 
    JSR .addSprite                                      

    PLA                                                 
    TAX                                                 
    DEX                                                 
    BNE .addSpriteLoop                                  

.return15 = $a67b
    RTS                                                 

§10. cantOpenFileError.

.cantOpenFileError = $a67c
    JSR .generateError                                  
    !byte $85                                           error number [NOTE: should be $84]
    !text "Can't open file",0                           error message

§11. Reads a sprite file.

 On Entry:
   .vduTempStoreDA/DB - filename address
   .vduTempStoreDC/DD - load address

 On Exit:
   Carry: clear on success
   A: number of sprites after reading the file
   vduTempStoreDC/D: end of sprites address
.readSpriteFile = $a690
    Store filename address to parameter block in private workspace
    LDY #.workspaceOffsetFilenameLow                    }
    LDA .vduTempStoreDA                                 }
    STA (.privateWorkspaceLow),Y                        } set filename address
    INY                                                 } i.e.
    LDA .vduTempStoreDB                                 }
                                                        } workspace[.workspaceOffsetFilenameLow]  = .vduTempStoreDA = filename address low
    STA (.privateWorkspaceLow),Y                        }
                                                        } workspace[.workspaceOffsetFilenameHigh] = .vduTempStoreDB = filename address high

    Store load address to parameter block in private workspace
    INY                                                 } Y=#.workspaceOffsetLoadAddressLow
    LDA .vduTempStoreDC                                 }
    STA (.privateWorkspaceLow),Y                        }
    INY                                                 }
    LDA .vduTempStoreDD                                 } set load address
    STA (.privateWorkspaceLow),Y                        }
    INY                                                 } i.e.
    LDA #$FF                                            } workspace[load address low] =
                                                        } .vduTempStoreDC (load address low)
    STA (.privateWorkspaceLow),Y                        } workspace[load address mid1] =
                                                        } .vduTempStoreDD (load address high)
    INY                                                 } workspace[load address mid2] = $FF
    STA (.privateWorkspaceLow),Y                        } workspace[load address high] = $FF

    We zero this next byte, meaning 'load the file at the load address given'
    INY                                                 } Y=#.workspaceOffsetExecAddressLow
    LDA #0                                              }
    STA (.privateWorkspaceLow),Y                        }
                                                        } workspace[.workspaceOffsetExecAddressLow] = 0

    Store load address
    LDY #.workspaceOffsetEndOfSpritesAddressLow         
    LDA .vduTempStoreDC                                 
    STA (.privateWorkspaceLow),Y                        workspace[end of sprites low] =
                                                        tempStoreDC
    INY                                                 
    LDA .vduTempStoreDD                                 
    STA (.privateWorkspaceLow),Y                        workspace[end of sprite high] =
                                                        tempStoreDD

    Open file for reading
    LDX .vduTempStoreDA                                 }
    LDY .vduTempStoreDB                                 } Pointer to filename
    LDA #$40                                            
    JSR .OSFIND                                         open file for reading

    CMP #0                                              
    BEQ .cantOpenFileError                              if (open file fails) then branch

    Read two bytes (the size) onto the stack
    TAY                                                 Y = file handle
    JSR .OSBGET                                         get first byte
    PHA                                                 push first byte of file
    JSR .OSBGET                                         get second byte
    PHA                                                 push second byte

    Close file
    LDA #0                                              
    JSR .OSFIND                                         close file

    JSR .getPrivateWorkspaceAddress                     

    Recall first two bytes from stack (size)
    PLA                                                 }
    STA .vduTempStoreDD                                 } .vduTempStoreDC/DD = first two
                                                        } bytes from file (size)
    PLA                                                 }
    STA .vduTempStoreDC                                 }

    Add size to current end of sprites address
    CLC                                                 }
    LDY #.workspaceOffsetEndOfSpritesAddressLow         }
    LDA (.privateWorkspaceLow),Y                        }
    ADC .vduTempStoreDC                                 }
    STA .vduTempStoreDC                                 } .vduTempStoreDC/DD +=
                                                        } workspace[$65/$66]
    INY                                                 } Y =
                                                        }
                                                        } .workspaceOffsetEndOfSpritesAddressHigh
    LDA (.privateWorkspaceLow),Y                        }
    ADC .vduTempStoreDD                                 }
    STA .vduTempStoreDD                                 }

    Check for enough room
    LDY #.workspaceOffsetSpriteEndPage                  
    LDA #0                                              
    CMP .vduTempStoreDC                                 
    LDA (.privateWorkspaceLow),Y                        
                                                        workspace[.workspaceOffsetSpriteEndPage] - .vduTempStoreDC/DD
    SBC .vduTempStoreDD                                 
    BCC .notEnoughRoomError                             if
                                                        
                                                        (workspace[.workspaceOffsetSpriteEndPage] < .vduTempStoreDC/DD) then branch

    Load file
    LDX #.workspaceOffsetParamBlock                     }
    LDY .privateWorkspaceHigh                           } address of parameter block
    LDA #$FF                                            load named file
    JSR .OSFILE                                         

    JSR .getPrivateWorkspaceAddress                     

    vduTempStoreDC/D = end of sprites address
    LDY #.workspaceOffsetEndOfSpritesAddressLow         }
    LDA (.privateWorkspaceLow),Y                        }
    STA .vduTempStoreDC                                 }
    INY                                                 }
    LDA (.privateWorkspaceLow),Y                        } .vduTempStoreDC/DD =
                                                        }
                                                        } workspace[.workspaceOffsetEndOfSpritesAddressLow/High]
    STA .vduTempStoreDD                                 }

    Get number of sprites
    LDY #2                                              }
    LDA (.vduTempStoreDC),Y                             } get number of sprites
    CLC                                                 }
    RTS                                                 

§12. notEnoughRoomError.

.notEnoughRoomError = $a71a
    JSR .generateError                                  
    !byte $85                                           error number
    !text "Not enough room",0                           error message

§13. Prepare the filing system by setting short messages on a cassette / ROM based filing system.

 and get the workspace address
.prepareFilingSystem = $a72e
    TXA                                                 }
    PHA                                                 }
    TYA                                                 } store X,Y
    PHA                                                 }

    LDA #0                                              }
    TAY                                                 } OSARGS 0,168,0
    LDX #$A8                                            }
    JSR .OSARGS                                         } return filing system number in A

    AND #$FC                                            
    BNE .restoreXY                                      if (not cassette or ROM filing
                                                        system) then branch

    LDA #$8B                                            }
    LDX #1                                              } *FX 139,1,1
    LDY #1                                              } Equivalent to *OPT 1,1
    JSR .OSBYTE                                         } (give short messages)

.restoreXY = $a747
    PLA                                                 
    TAY                                                 
    PLA                                                 
    TAX                                                 
    JMP .getPrivateWorkspaceAddress                     

§14. *SCHOOSE n.

 On Entry:
   XY is the rest of the command line
.starSChoose = $a74e
    JSR .read8BitNumberIntoA                            
.sChooseA = $a751
    JSR .starSChooseInternal                            
    BEQ .spriteDoesntExistError                         
    RTS                                                 

§15. spriteDoesntExistError.

.spriteDoesntExistError = $a757
    JSR .generateError                                  
    !byte $86                                           error number
    !text "Sprite doesn't exist",0                      error message

§16. starSChooseInternal.

.starSChooseInternal = $a770
    PHA                                                 
    LDY #.workspaceOffsetSpritePages                    
    LDA (.privateWorkspaceLow),Y                        
    BEQ .schooseError                                   if no sprite space, then branch
                                                        (error)
    PLA                                                 
    JSR .findSpriteA                                    
    BEQ .dontStoreSpriteAddress                         if sprite not found, then skip
                                                        storing the address

    Record the sprite address
    LDY #.workspaceOffsetCurrentSpriteAddressLow        
    STA (.privateWorkspaceLow),Y                        
    INY                                                 
    LDA .vduTempStoreDD                                 
    STA (.privateWorkspaceLow),Y                        

    CPX #0                                              
    RTS                                                 

.dontStoreSpriteAddress = $a789
    LDY #.workspaceOffsetCurrentSpriteAddressLow        }
    TXA                                                 }
    STA (.privateWorkspaceLow),Y                        } zero the current sprite address
    INY                                                 }
    STA (.privateWorkspaceLow),Y                        }
    CPX #0                                              
    RTS                                                 

.schooseError = $a794
    JMP .noSpriteMemoryError                            

§17. *SRENUMBER n,m.

 On Entry:
   XY is the rest of the command line
.starSRenumber = $a797
    JSR .read8BitNumberIntoA                            read first number n

    PHA                                                 push n
    JSR .skipLeadingSpaces                              

    STX .vduTempStoreDE                                 } remember address of remainder of
                                                        } command
    STY .vduTempStoreDF                                 }

    PLA                                                 pull n
    PHA                                                 push n
    JSR .findSpriteA                                    get sprite n address
    BEQ .spriteNotFound                                 if not found then branch

    Skip comma
    LDY #0                                              
    LDA (.vduTempStoreDE),Y                             
    CMP #','                                            
    BNE .missingCommaError                              

    Move on to next character
    LDX .vduTempStoreDE                                 
    LDY .vduTempStoreDF                                 
    INX                                                 
    BNE +                                               
    INY                                                 
+

    JSR .read8BitNumberIntoA                            read second number m

    PLA                                                 pull n
    PHA                                                 push n
    CMP .vduTempStoreDE                                 
    BEQ .spriteNumbersAreEqualError                     if (n == m) then branch

    LDA .vduTempStoreDE                                 get m
    PHA                                                 push m
    JSR .deleteSpriteInternal                           

    PLA                                                 get m
    STA .vduTempStoreDE                                 store m
    PLA                                                 pull n
    JSR .findSpriteA                                    get sprite address for sprite n

    LDY #.spriteHeaderOffsetSpriteNumber                
    LDA .vduTempStoreDE                                 get sprite number m
    STA (.vduTempStoreDC),Y                             store sprite number m
    RTS                                                 

.spriteNotFound = $a7d6
    JMP .spriteDoesntExistError                         

§18. missingCommaError.

.missingCommaError = $a7d9
    JSR .generateError                                  
    !byte $87                                           error number
    !text "Missing comma",0                             error message

§19. spriteNumbersAreEqualError.

.spriteNumbersAreEqualError = $a7eb
    JSR .generateError                                  
    !byte $88                                           error number
    !text "Sprite numbers are equal",0                  error message