Sparse Invaders Source - SpriteControllert.txt

From Retrosoftware

(Difference between revisions)
Jump to: navigation, search
(Sparse Invadeers Soruce - SpriteController.txt)
Current revision (22:36, 9 November 2009) (edit) (undo)
(Sparse Invaders Soruce - SpriteController.txt)
 
Line 1: Line 1:
-
== Sparse Invaders Soruce - SpriteController.txt ==
+
== Sparse Invaders Source - SpriteController.txt ==
The Sprite Controller manages any active sprites. This was the first module I really implemented when first working on the Sparse Invaders. That's really trying to explain that it's a little overly complex for the Beeb. In Sparse Invaders, the only sprites under this controller are the player, bullets, mothership and explosions. If you are to use this sprite controller then please be aware that it has limitations. To keep the game running faster the Invaders are drawn using a much more simplier and faster technique.
The Sprite Controller manages any active sprites. This was the first module I really implemented when first working on the Sparse Invaders. That's really trying to explain that it's a little overly complex for the Beeb. In Sparse Invaders, the only sprites under this controller are the player, bullets, mothership and explosions. If you are to use this sprite controller then please be aware that it has limitations. To keep the game running faster the Invaders are drawn using a much more simplier and faster technique.

Current revision

Sparse Invaders Source - SpriteController.txt

The Sprite Controller manages any active sprites. This was the first module I really implemented when first working on the Sparse Invaders. That's really trying to explain that it's a little overly complex for the Beeb. In Sparse Invaders, the only sprites under this controller are the player, bullets, mothership and explosions. If you are to use this sprite controller then please be aware that it has limitations. To keep the game running faster the Invaders are drawn using a much more simplier and faster technique. However that said, when initializing the sprite, it does pre-calculate and store certain parameters within the sprite structure to speed things along alittle when drawing the sprite. There are certainly pro's and con's when using this controller, however for simple games this more then does the job.

Please refer to constants.txt for details for the sprite structure.


  ;-------------------------------------------------------------------------------
   ;  SpriteController
   ;  Written by Neil Beresford.
   ;
   ;  Copyright 2008,2009 Neil Beresford
   ;
   ;    This file is part of Sparse Invaders.
   ;    Sparse Invaders is free software: you can redistribute it and/or modify
   ;    it under the terms of the GNU General Public License as published by
   ;    the Free Software Foundation, either version 3 of the License, or
   ;    (at your option) any later version.
   ;
   ;    Sparse Invaders is distributed in the hope that it will be useful,
   ;    but WITHOUT ANY WARRANTY; without even the implied warranty of
   ;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   ;    GNU General Public License for more details.
   ;
   ;    You should have received a copy of the GNU General Public License
   ;    along with Sparse Invaders.  If not, see <http://www.gnu.org/licenses/>.
   ;
   ;
   ;   Notes:
   ;
   ;  Sprite fix array, screen active list
   ;
   ;  Functionality...
   ;  Sprite core system:
   ;     SpriteInit           - pressetup for sprite system - holds test code at present.
   ;     SpriteStart          - Adds sprite into control system
   ;     SpritesDrawActive    - Draws all activate sprites - max limit of 6
   ;     SpritesWipeActive    - Wipes the area that the sprite was drawn to
   ;     SpriteDraw           - sprite drawer
   ;     SpriteWipe           - sprite wipe
   ;
   ;  Support Functionality;
   ;     SpriteClear          - clears the sprite structure within the active array
   ;     SpriteActivate       - marks the active position within 
   ;     SpriteCalcScreenPos  - calculates the screen position address from X,Y
   ;     SpriteRetreiveDetails- gets the sprite data, width and height for the sprite from its data
   ;
   ;-------------------------------------------------------------------------------

   .require "Constands"
   .require "Macros"


   ;-------------------------------------------------------------------------------
   ; SpriteInit - 
   ;     inits the sprite system
   ;
   ;-------------------------------------------------------------------------------
   SpriteInit:

      ; clear the sprite data ...
      ; [NOTE] this assumes at present, less then 255 bytes for the data ... 
      LDA  #0
      LDX  #TOTAL_SPRITE_SPACE 

   SI_Clearlist:

      DEX
      STA  SPRArray,X
      BNE  SI_Clearlist

      ; clear the active list ...
      LDX  #TOTAL_ACTIVE_SPRITES - 1
      LDA #$ff

   SI_ClearActives:   

      STA  SPRActive,X
      DEX
      BPL  SI_ClearActives


      RTS
 

   ;-------------------------------------------------------------------------------
   ;  SpriteStart:   
   ;         Starts the sprite, activating it...
   ;   Regs - A sprite number for storage. (SprArray)
   ;          X sprite X
   ;          Y sprite Y
   ;     SPRITE sprite frame  <--- SPRITE is in Zero page
   ; CALLPARMA1 used for the callback for the control... 
   ; CALLPARMA2 ... ( have blank if not needed ) 
   ;-------------------------------------------------------------------------------
   SpriteStart:

      CLC
      ROL
      ROL
      ROL
      ROL
      STA  SCRATCH1
      STX  XPOS
      STY  YPOS

      JSR  SpriteClear
      LDA  SCRATCH1
      JSR  SPriteActivate
      STX   CURRENT_SPRITE

      CLC
      LDA   #<SPRArray
      ADC   SCRATCH1
      STA   TEMPPTR
      LDA   #>SPRArray
      ADC   #0
      STA   TEMPPTR+1

      LDY   #0   
      LDA   XPOS                ; 0 Xpos
      STA   (TEMPPTR), Y 
      INY
      LDA   YPOS                ; 1 Ypos
      STA   (TEMPPTR), Y 
      INY
      LDA   SPRITE              ; 2 frame
      STA   (TEMPPTR), Y    
      INY
      LDA   CALLPARAM1          ; 3 control
      STA   (TEMPPTR), Y 
      LDA   CALLPARAM2
      INY
      STA   (TEMPPTR), Y        ; 4 ... 
                        

      ; PLEASE PLEASE do not move this away from the YPOS adjust as I did! Sigh!
      LDA   SPRITE
      JSR   SpriteRetreiveDetails
      LDY   #SPRBLK_WIDTH
      STA   (TEMPPTR), Y        ; store width
      TXA
      INY
      STA   (TEMPPTR), Y        ; store height
     
      ; adjust Y pos to bottom of sprite,
      CLC
      ADC  YPOS
      SEC
      SBC  #1
      STA  YPOS

      ; adjust the YPOS to character based and store the offset in x for indexing
      AND  #$07
      STA  XOFFSET
      LDA  YPOS
      AND  #$f8
      STA  YPOS
      jsr   SpriteCalcScreenPos
      
      LDA   #SPRFLAG_REDRAW
      LDY   #SPRBLK_FLAG
      STA   (TEMPPTR), Y        ; Mark the sprite for redraw

      LDY   #SPRBLK_SPRDATA
      LDA   CURRENTSPRITEDATA
      STA   (TEMPPTR),Y         ; store sprite data  
      INY
      LDA   CURRENTSPRITEDATA+1  
      STA   (TEMPPTR),Y  

      LDY   #SPRBLK_XOFFSET    ; Xoffset
      LDA   XOFFSET
      STA   (TEMPPTR),Y    
      LDY   #SPRBLK_XOFFBACK
      STA   (TEMPPTR),Y
      LDA   SCREENADD          ; 6 SCREEN ADD
      LDY   #SPRBLK_SCREENADD
      STA   (TEMPPTR),Y    
      INY
      LDA   SCREENADD+1        ; 7  /\  /\
      STA   (TEMPPTR),Y    

      LDY   #SPRBLK_SCRBACK    ; screen position used for wiping spr
      LDA   SCREENADD
      STA   (TEMPPTR),Y
      INY
      LDA   SCREENADD+1
      STA   (TEMPPTR),Y

   SI_Debug:
       
      RTS

   ;-------------------------------------------------------------------------------
   ; SpriteMoveSprite - 
   ;     Moves the sprite to the adsolute pos passed in
   ;     A - sprite slot index ( sprite * 8 )
   ;     X - x pos
   ;     y - y pos
   ;-------------------------------------------------------------------------------
   SpriteMoveSprite:

      CLC
      ROL
      ROL
      ROL
      ROL
      STA  SCRATCH1
      STX  XPOS
      STY  YPOS

      CLC
      LDA   #<SPRArray
      ADC   SCRATCH1
      STA   TEMPPTR
      LDA   #>SPRArray
      ADC   #0
      STA   TEMPPTR+1

   SpriteMoveSpr:

      ; store the x and y position
      LDA   XPOS
      LDY   #SPRBLK_X
      STA   (TEMPPTR), Y
      LDA   YPOS
      INY
      STA   (TEMPPTR), Y
      
            
      ; get the width and height for drawing the sprite
      LDY   #SPRBLK_WIDTH
      LDA   (TEMPPTR), Y
      STA   WIDTH
      INY
      LDA   (TEMPPTR), Y
      STA   HEIGHT


      ; adjust Y pos to bottom of sprite,
      CLC
      ADC  YPOS
      SEC
      SBC  #1
      STA  YPOS

      ; adjust the YPOS to character based and store the offset in x for indexing
      AND  #$07
      STA  XOFFSET
      LDA  YPOS
      AND  #$f8
      STA  YPOS
      jsr   SpriteCalcScreenPos

    
      LDA   XOFFSET
      LDY   #SPRBLK_XOFFSET    ; 5 Xoffset
      STA   (TEMPPTR),Y    
      LDA   SCREENADD          ; 6 SCREEN ADD
      INY
      STA   (TEMPPTR),Y    
      LDA   SCREENADD+1        ; 7  /\  /\
      INY
      STA   (TEMPPTR),Y    

      LDY   #SPRBLK_FLAG
      LDA   (TEMPPTR), Y
      ORA   #SPRFLAG_REDRAW
      STA   (TEMPPTR), Y        ; Mark the sprite for redraw

      RTS

   ;-------------------------------------------------------------------------------
   ; SpriteActivate - 
   ;     Activates the sprite slot
   ;     A - sprite slot index ( sprite * 8 )
   ;-------------------------------------------------------------------------------
   SpriteActivate:

      TAY
      
      LDX   #TOTAL_ACTIVE_SPRITES-1
      LDA   #$ff

   SA_Loop:

      CMP   SPRActive,X
      BEQ   SA_found
      DEX
      BPL   SA_loop
      RTS

   SA_found:

      TYA
      STA   SPRActive,X
      RTS
         
   ;-------------------------------------------------------------------------------
   ; SpriteClear - 
   ;     clears sprite data and removes from active list if present..
   ;     A - sprite slot indexed ( sprite * 16 )
   ;
   ;-------------------------------------------------------------------------------
   SpriteClear:

      PHA   
      ; firstly check and remove if found in active list
      LDX   #TOTAL_ACTIVE_SPRITES-1

   SC_checkActive:   

      CMP  SPRActive,X
      BNE  SC_decIndex

   SC_foundActive:   

      LDA  #$ff
      STA  SPRActive,X


      ; now clear the sprite slot ...

      PLA

   SC_ClearData:

      STA  SCRATCH1
      LDA  #<SPRArray
      CLC
      ADC  SCRATCH1
      STA  TEMPPTR
      LDA  #>SPRArray
      ADC  #0
      STA  TEMPPTR+1
      
      LDY  #SIZEOF_SPRITE_BLOCK -1  

   SC_clear:

      STA  (TEMPPTR),Y
      DEY
      BPL  SC_clear

      RTS

   SC_decIndex:

      DEX
      BPL  SC_checkActive
      PLA           ; pop stack...
      RTS




   ;-------------------------------------------------------------------------------
   ; SpriteDrawActive
   ;        worth through the active sprites, drawing any that are needed.
   ;-------------------------------------------------------------------------------
   SpritesDrawActive:

      ; firstly check and remove if found in active list
      LDX   #TOTAL_ACTIVE_SPRITES-1

   SDA_Loop:

      STX   ACTIVEINDEX
      LDA   SPRActive,X
      CMP   #$ff
      BEQ   SDA_Next
      
   SDA_Found:

      ; calculate the offset to the start of active sprite data
      STA   SPRITE
      CLC
      LDA   #<SPRArray
      ADC   SPRITE
      STA   TEMPPTR
      LDA   #>SPRArray
      ADC   #0
      STA   TEMPPTR+1

      LDY   #SPRBLK_FLAG
      LDA   (TEMPPTR),Y
      AND   #SPRFLAG_REDRAW
      BEQ   SDA_Next

      STX   SCRATCH1
            
      jsr SDA_SetupSprite 
    
      LDX   STOREX
      LDY   STOREY

      ; draw the sprite to screen...

      JSR   SpriteDraw

      ; clear the redraw flag...
      LDY   #SPRBLK_FLAG
      LDA   (TEMPPTR),Y
      AND   #SPRFLAG_NOT_REDRAW
      STA   (TEMPPTR),Y


      LDY   #SPRBLK_CTRL   
      LDA   (TEMPPTR),Y
      BEQ   SDA_Next

      STA   USERPTR
      INY
      LDA   (TEMPPTR),Y
      STA   USERPTR+1


      ; NOTE - RTS pops the low then high byte, adds one
      ; then sets the PC to that address. The example in
      ; 6502.org shows the high byte od SDA_Return with -1
      ; on it as well. I can only assume it's parsed left 
      ; to right -  I'm concerned if this address falls on a 256
      ; boundary.
      ; might be a bug in p65 - investigate later, as address calculated
      ; correctly as of writting. 

      LDA   #>SDA_Return
      PHA
      LDA   #<SDA_Return-1
      PHA
      JMP   (USERPTR)

   SDA_Return:
   SDA_Next:
      
      LDX   ACTIVEINDEX   
      DEX
      BPL   SDA_Loop

      RTS

   SDA_SetupSprite:

      ; get the x and y and frame for drawing the sprite
      LDY   #0
      LDA   (TEMPPTR), Y
      STA   STOREX
      INY
      LDA   (TEMPPTR), Y
      STA   STOREY
      INY
      LDA   (TEMPPTR), Y

      TAX                          ; frame saved

      ; retrieve the screen position for drawing the sprite ...

      LDY   #SPRBLK_XOFFSET        ; sprite screen drawing
      LDA   (TEMPPTR), Y
      STA   XOFFSET   
      INY
      LDA   (TEMPPTR), Y
      STA   SCREENADD   
      STA   SCREENADD_BACK   
      INY
      LDA   (TEMPPTR), Y
      STA   SCREENADD+1
      STA   SCREENADD_BACK+1   

      LDY   #SPRBLK_WIDTH          ; sprite width and height
      LDA   (TEMPPTR), Y
      STA   WIDTH
      STA   CURRENT_SPR_W   
      INY
      LDA   (TEMPPTR), Y
      STA   HEIGHT
      STA   CURRENT_SPR_H   

      LDY   #SPRBLK_SPRDATA        ; sprite data          
      LDA   (TEMPPTR),Y
      STA   CURRENTSPRITEDATA
      INY
      LDA   (TEMPPTR),Y
      STA   CURRENTSPRITEDATA+1

      TXA
      RTS


   ;-------------------------------------------------------------------------------
   ; SpriteWipeActive
   ;        worth through the active sprites, clearing any that are needed.
   ;-------------------------------------------------------------------------------
   SpritesWipeActive:

      ; firstly check and remove if found in active list
      LDX   #TOTAL_ACTIVE_SPRITES-1

   SWA_Loop:
      STX   ACTIVEINDEX

      LDA   #$ff
      CMP   SPRActive,X
      BEQ   SWA_Next
      
   SWA_Found:

      LDA   SPRActive,X
      STA   SPRITE
      
      ; check the redraw flag ...
      CLC
      ADC   #SPRBLK_FLAG   
      TAX
      LDA   SPRArray,X

      AND   #SPRFLAG_REDRAW
      BEQ   SWA_Next
      
      ; clear the sprite to screen...

      LDA   SPRITE
      JSR   SpriteWipe

      ;
      ; tempptr has been set within the spritewipe function
      ; Set the new screen position to be the old one ...

      LDY   #SPRBLK_FLAG
      LDA   (TEMPPTR),Y
      AND   #SPRFLAG_KILL
      BEQ   SWA_SetScreen   

      ; kill sprite ... remove from list
      LDX   ACTIVEINDEX
      LDA   #$ff
      STA   SprActive,X

      JMP   SWA_Next

   SWA_SetScreen:
      
      LDY   #SPRBLK_SCREENADD
      LDA   (TEMPPTR),Y
      LDY   #SPRBLK_SCRBACK
      STA   (TEMPPTR),Y
      LDY   #SPRBLK_SCREENADD2
      LDA   (TEMPPTR),Y
      LDY   #SPRBLK_SCRBACK2
      STA   (TEMPPTR),Y

      LDY   #SPRBLK_XOFFSET
      LDA   (TEMPPTR),Y
      LDY   #SPRBLK_XOFFBACK
      STA   (TEMPPTR),Y

   SWA_Next:
      
      LDX   ACTIVEINDEX
      DEX
      BPL   SWA_Loop

      RTS

   ;-------------------------------------------------------------------------------
   ; SpriteRetreiveDetails - a Sprite number
   ;              returns A - width, X - heighht
   ;
   ;-------------------------------------------------------------------------------
   SpriteRetreiveDetails:

      ; calculate the index...
      ASL 
      TAX
      CLC
      
      ; get and store the pointer to the sprtie data ...   
      LDA  spriteData,X
      ADC  #<spriteData
      STA  CURRENTSPRITEDATA
      INX
      LDA  spriteData,X
      ADC  #>spriteData
      STA  CURRENTSPRITEDATA+1

      ; grab the sprite info ...
      LDY  #SPRDATA_HEIGHT
      LDA  (CURRENTSPRITEDATA),Y
      TAX
      DEY
      LDA  (CURRENTSPRITEDATA),Y
      
      RTS




   ;-------------------------------------------------------------------------------
   ; SpriteDraw - a Sprite number = referenced from SPRArray
   ;              The following need to be setup prior to calling this...
   ;              SPRITEADD, WIDTH, HEIGHT, XOFFSET, CURRENTSPRITEDATA
   ;-------------------------------------------------------------------------------
   SpriteDraw:

      ; store the sprite number, x and y position
      STA  SPRITE
      STX  XPOS
      STY  YPOS
    
      ; now store sprite data and screen address in code
      LDA  SCREENADD
      STA  ScreenAddPtr+1
      LDA  SCREENADD+1
      STA  ScreenAddPtr+2
      
      CLC
      LDA  CURRENTSPRITEDATA
      ADC  #2
      STA  SpriteDataPtr+1
      LDA  CURRENTSPRITEDATA+1
      ADC  #0
      STA  SpriteDataPtr+2

      LDX  XOFFSET
      
   SW_Width:

      LDY  HEIGHT
      DEY

   SW_Height:   

   SpriteDataPtr:         ; please note - self modifying code
      LDA  $FFFF,Y        
      BEQ  SW_SkipWrite

    ScreenAddPtr:          ; please note - self modifying code
      STA  $FFFF,X       ; is ->   STA  ScreenAddPtr+1,X

   SW_SkipWrite:
      
      DEX
      BPL  SW_CheckHeight

   SW_AtCharPos:

      SEC
      LDA  ScreenAddPtr+1
      SBC  #$80
      STA  ScreenAddPtr+1
      LDA  ScreenAddPtr+2
      SBC  #2
      STA  SCreenAddPtr+2
      
      LDX  #7

   SW_CheckHeight:

      DEY
      BPL  SW_Height
      DEC  WIDTH
      BEQ  SW_End
     
      
      ; move to the next column
      
      CLC
      LDA  SpriteDataPtr+1
      ADC  HEIGHT
      STA  SpriteDataPtr+1
      LDA  SpriteDataPtr+2
      ADC  #0
      STA  SpriteDataPtr+2
         
      LDA  SCREENADD
      CLC
      ADC  #8
      STA  SCREENADD
      STA  ScreenAddPtr+1
      LDA  SCREENADD+1
      ADC  #0
      STA  SCREENADD+1
      STA  ScreenAddPtr+2

      LDX  XOFFSET
      JMP  SW_Width

   SW_End:
      
      RTS
   ;-------------------------------------------------------------------------------
   ; SpriteNoMaskDraw - a Sprite number = referenced from SPRArray
   ;              The following need to be setup prior to calling this...
   ;              SPRITEADD, WIDTH, HEIGHT, XOFFSET, CURRENTSPRITEDATA
   ;-------------------------------------------------------------------------------
   SpriteNoMaskDraw:

      ; store the sprite number, x and y position
      STA  SPRITE
      STX  XPOS
      STY  YPOS
      
      ; now store sprite data and screen address in code
      LDA  SCREENADD
      STA  SScreenAddPtr+1
      LDA  SCREENADD+1
      STA  SScreenAddPtr+2
      
      CLC
      LDA  CURRENTSPRITEDATA
      ADC  #2
      STA  SSpriteDataPtr+1
      LDA  CURRENTSPRITEDATA+1
      ADC  #0
      STA  SSpriteDataPtr+2

      LDX  XOFFSET
      
   SNMW_Width:

      LDY  HEIGHT
      DEY

   SNMW_Height:   

    SSpriteDataPtr:         ; please note - self modifying code
     LDA  $FFFF,Y        
   SScreenAddPtr:          ; please note - self modifying code
      STA  $FFFF,X       ; is ->   STA  ScreenAddPtr+1,X

      DEX
      BPL  SNMW_CheckHeight

   SNMW_AtCharPos:

      SEC
      LDA  SScreenAddPtr+1
      SBC  #$80
      STA  SScreenAddPtr+1
      LDA  SScreenAddPtr+2
      SBC  #2
      STA  SSCreenAddPtr+2
      
      LDX  #7

   SNMW_CheckHeight:

      DEY
      BPL  SNMW_Height
      DEC  WIDTH
      BEQ  SNMW_End
     
      
      ; move to the next column
      
      CLC
      LDA  SSpriteDataPtr+1
      ADC  HEIGHT
      STA  SSpriteDataPtr+1
      LDA  SSpriteDataPtr+2
      ADC  #0
      STA  SSpriteDataPtr+2
         
      LDA  SCREENADD
      CLC
      ADC  #8
      STA  SCREENADD
      STA  SScreenAddPtr+1
      LDA  SCREENADD+1
      ADC  #0
      STA  SCREENADD+1
      STA  SScreenAddPtr+2

      LDX  XOFFSET
      JMP  SNMW_Width

   SNMW_End:
      
      RTS

   ;-------------------------------------------------------------------------------
   ; SpriteWipe - a Sprite number
   ;-------------------------------------------------------------------------------
   SpriteWipe:

      STA   SCRATCH1
      CLC
      LDA   #<SPRArray
      ADC   SCRATCH1
      STA   TEMPPTR
      LDA   #>SPRArray
      ADC   #0
      STA   TEMPPTR+1

      LDY   #SPRBLK_XOFFBACK
      LDA   (TEMPPTR),Y
      STA   XOFFSET

      LDY   #SPRBLK_SCRBACK
      LDA   (TEMPPTR),Y
      STA   SCREENADD
      INY
      LDA   (TEMPPTR),Y
      STA   SCREENADD+1

      LDY   #SPRBLK_WIDTH
      LDA   (TEMPPTR),Y
      STA   WIDTH
      INY
      LDA   (TEMPPTR),Y
      STA   HEIGHT

   Sprite_Blank:

      ; now store screen address in code
      LDA  SCREENADD
      STA  ScreenAddPtr2+1
      LDA  SCREENADD+1
      STA  ScreenAddPtr2+2
      
      LDX  XOFFSET

   SWipe_Width:

      LDY  HEIGHT
      DEY

   SWipe_Height:   

      LDA  #$00 
   ScreenAddPtr2:          ; please note - self modifying code
      STA  $FFFF,X         ; is ->   STA  ScreenAddPtr+1,X

   SWipe_SkipWrite:
      
      DEX
      BPL  SWipe_CheckHeight

   SWipe_AtCharPos:

      SEC
      LDA  ScreenAddPtr2+1
      SBC  #$80
      STA  ScreenAddPtr2+1
      LDA  ScreenAddPtr2+2
      SBC  #2
      STA  SCreenAddPtr2+2
      
      LDX  #7

   SWipe_CheckHeight:

      DEY
      BPL  SWipe_Height
      DEC  WIDTH
      BEQ  SWipe_End
     
      
      ; move to the next column
      LDA  SCREENADD
      CLC
      ADC  #8
      STA  SCREENADD
      STA  ScreenAddPtr2+1
      LDA  SCREENADD+1
      ADC  #0
      STA  SCREENADD+1
      STA  ScreenAddPtr2+2

      LDX  XOFFSET
      JMP  SWipe_Width

   SWipe_End:
      
      RTS



   ;-------------------------------------------------------------------------------
   ;  SpriteCalcScreenPos:
   ;    calculates the screen address - please note that 
   ;    xpos($75) and ypos($76) need to be set up before.
   ;    This also uses $70+$71 for the screen address ( screenAdd )
   ;
   ;-------------------------------------------------------------------------------
   SpriteCalcScreenPos:

      ; reset the screen address ... 
      LDA  #SCREENLOW
      STA  SCREENADD
      LDA  #SCREENHIGH
      STA  SCREENADD+1 


      ; now calculate the Y position in chars ( *640 ) and add
      ; to the screen Address
      LDA  YPOS
      AND  #$f8
      LSR
      LSR
      TAY
      CLC
      LDA  LookUp640, Y
      ADC  SCREENADD
      STA  SCREENADD
      INY
      LDA  LookUp640,Y 
      ADC  SCREENADD+1
      STA  SCREENADD+1


      ; now the X multiply then addition to screen address    
      `MUL8ADDTOADDRESS XPOS, SCREENADD

      ; finally the first 3 bits of the YPos
      LDA  YPOS
      AND  #$07
      CLC
      ADC  SCREENADD
      STA  SCREENADD


      LDA  SCREENADD
      STA  SCREENADD_BACK
      LDA  SCREENADD+1
      STA  SCREENADD_BACK+1

      RTS

   ;-------------------------------------------------------------------------------
   ;
   ;  Sprite_SetFlag
   ;     A - SPrite slot * 16
   ;     X - bits to set...
   ;
   ;-------------------------------------------------------------------------------
   Sprite_SetFlag:

      STX  SCRATCH1
      CLC
      ADC  #SPRBLK_FLAG
      TAX
      LDA  SprArray,X
      ORA  SCRATCH1
      STA  SPrArray,X
    
      RTS



   ;-------------------------------------------------------------------------------

   ; TOTAL_SPRITE_SPACE = 8 * 15 sprites = 240 bytes     
   SPRArray: .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
   SPRActive:
             .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff            ; the eight active sprites ... 
   ;-------------------------------------------------------------------------------

   LookUp640:
      .incbin "LookUpTable640"

   SpriteData:
      .incbin "Sprites"

   ;-------------------------------------------------------------------------------