

sprite_routines.asm
MoveSpriteLeft
In this subroutine MoveSpriteLeft, we first get the value in the variable (SPRITE_POS_X), which holds the sprite to character’s X position. If it’s not a zero here then no change has happened to the Sprite’s X MSB position and we skip to “decNoChange which continues to move the variable (SPRITE_POS_X).
Otherwise we have crossed the MSB X area as the Sprite moves to the left. We first decrease the variable (SPRITE_POS_X_EXTEND) which moves Sprite X backward.
Then we check a table in (BIT_TABLE) and see if the X extended bit has been set or not. Finally we store the new results into the variable (SPRITE_POS_X_EXTEND) and (VIC_SPRITE_X_EXTEND – $D010 (53264). The BIT_TABLE looks like this:
BIT_TABLE byte 1,2,4,8,16,32,64,128
;=================================================================================================== ; Moves a sprite left one pixel - using the whole screen (with the X extended bit) ; X = number of hardware sprite to move (0 - 7) - Register is left intact ; ; NOTE : to move a sprite multiple pixels, you call this multiple times. One day I might have a crack ; at doing one for multiple pixels, but at this point I don't think I could do one that would ; justify the extra code and provide a performance boost to make it worthwhile. ;--------------------------------------------------------------------------------------------------- ; Fixed bug in the strange extended bit behavior. Flipping the bit on negative flag sets it on $FF ; but also flips it on every other change from 128 ($80) to 255 ($FF) making it flicker. ; Checking instead for 0 corrects this. ;--------------------------------------------------------------------------------------------------- lda SPRITE_POS_X,x ; First check for 0 (NOT negative) bne @decNoChange ; branch if NOT 0 dec SPRITE_POS_X,x ; Decrement Sprite X position by 1 (to $FF) lda BIT_TABLE,x ; fetch the bit needed to change for this sprite eor SPRITE_POS_X_EXTEND ; use it as a mask to flip the correct X extend bit sta SPRITE_POS_X_EXTEND ; store the data then save it in the VIC II register sta VIC_SPRITE_X_EXTEND ; $D011 - Sprite extended X bits (one bit per sprite) jmp @noChangeInExtendedFlag ; Jump to saving the X position
@decNoChange
; Not zero X so we decrement dec SPRITE_POS_X,x
Reading from variable (SPRITE_POS_X) we now shift a bit left in the accumulator and save the result in the Y register. After this we get the variable (SPRITE_POS_X) value and save it in the variable (VIC_SPRITE_POS_X) which handles our Sprite’s X position. Then we reduce the Sprite’s X delta position (going left) using the variable (SPRITE_POS_X_DELTA). The delta tells how far a Sprite’s has passed through pixels 0-4. If the Sprite’s delta X position > 0 then we are done here.
@noChangeInExtendedFlag
txa ; copy X to the accumulator (sprite number) asl ; shift it left (multiply by 2) tay ; save it in Y (to calculate the register to save to) lda SPRITE_POS_X,x ; Load our variable saved X position sta VIC_SPRITE_X_POS,y ; save it in $D000 offset by Y to the correct VIC ; sprite register ; Here we decrement the Sprite delta - we moved ; a pixel so the delta goes down by one dec SPRITE_POS_X_DELTA,x bmi @resetDelta; test for change to negative rts ; if delta is still > 0 we're done
Finally we set the Sprite X delta’s position variable (SPRITE_POX_X_DELTA) to 7. Then we decrease the Sprite’s X character position using the variable (SPRITE_CHAR_POS_X).
@resetDelta
lda #$07 ; if delta falls below 0 sta SPRITE_POS_X_DELTA,x ; reset it to #$07 - one char dec SPRITE_CHAR_POS_X,x ; delta has reset - so decrement character position rts
MoveSpriteRight
For the first part of the subroutine MoveSpriteRight we increase the Sprite’ X position using the variable (SPRITE_POS_X). We also check to make sure it’s not at zero, or else we branch to “@noChangeInExtendedFlag”.
In this section we check the X extended bit table (BIT_TABLE). Then we flip the extended bit when the Sprite’s X position reached zero, which will set it to one. This “one” is necessary to move the Sprite past the 256th position (setting the high bit). Then we save the results in the variable (SPRITE_POS_X_EXTEND) and the variable (VIC_SPRITE_X_EXTEND), which is $D010 (53264) and manages the MSB of our Sprite’s X position.
;=================================================================================================== ; Moves a sprite right one pixel and adjusts the extended X bit if needed to carry to all the way ; across the screen. ; X = the number of the hardware sprite to move - this register is left intact ; ; NOTE : to move a sprite multiple pixels, this routine must be called multiple times ;--------------------------------------------------------------------------------------------------- inc SPRITE_POS_X,x ; increase Sprite X position by 1 ; lda SPRITE_POS_X,x ; load the sprite position bne @noChangeInExtendedFlag ; if not #$00 then no change in x flag lda BIT_TABLE,x ; get the correct bit to set for this sprite eor SPRITE_POS_X_EXTEND ; eor in the extended bit (toggle it on or off) sta SPRITE_POS_X_EXTEND ; store the new flags sta VIC_SPRITE_X_EXTEND ; set it in the VIC register
Now we get the Sprite’s X position, multiply it by 2 and move the result to the Y register. Next we check the variable (SPRITE_POS_X) and save the result in the variable (VIC_SPRITE_X_POS). Then we increment the variable (SPRITE_POS_X_DELTA) to be sure the delta pixel values are staying consistent with our Sprite’s movement.
@noChangeInExtendedFlag
txa ; transfer the sprite # to A asl ; multiply it by 2 tay ; transfer the result to Y lda SPRITE_POS_X,x ; copy the new position to our variable sta VIC_SPRITE_X_POS,y ; update the correct X position register in the VIC ; Our X position is now incremented, so delta also ; increases by 1 inc SPRITE_POS_X_DELTA,x
After this we check the variable (SPRITE_POS_X_DELTA), mask out values between 0-7 and check to see the delta values are at zero and clear the variables (SPRITE_POS_X_DELTA) and finally we increase the variable (SPRITE_CHAR_POS_X) since there is a character boundary that exists at this point.
lda SPRITE_POS_X_DELTA,x and #%0111 ; Mask it to 0-7 ; cmp #$08 ; if it's crossed over to 8, we reset it to 0 beq @reset_delta rts ; if it hasn't we're done @reset_delta @reset_delta sta SPRITE_POS_X_DELTA,x ; reset delta to 0 - this means we've crossed a inc SPRITE_CHAR_POS_X,x ; a character boundry, so increase our CHAR position rts
MoveSpriteUp
The subroutine MoveSpriteUp involves decreasing the variable (SPRITE_POS_Y) and store it in the variable (VIC_SPRITE_Y_POS). Then we simply decrease the variable (SPRITE_POS_Y_DELTA) to manage the Sprite’s Y delta position and check it for a reset, setting a value of 7 in (SPRITE_POS_Y_DELTA) and finally we decrease the variable (SPRITE_CHAR_POS_Y) once the delta has been reset since we have crossed a character border.
;=================================================================================================== ; Up and down have no special considerations to consider - they wrap at 255 ; X = number of hardware sprite to move ;--------------------------------------------------------------------------------------------------- dec SPRITE_POS_Y,x ; decrement the sprite position variable txa ; copy the sprite number to A asl ; multiply it by 2 tay ; transfer it to Y lda SPRITE_POS_Y,x ; load the sprite position for this sprite sta VIC_SPRITE_Y_POS,y ; send it to the correct VIC register - $D001 + y ; Y position has decreased, so our delta decreases dec SPRITE_POS_Y_DELTA,x bmi @reset_delta ; test to see if it drops to negative rts ; if not we're done
@reset_delta
lda #$07 ; reset the delta to 0 sta SPRITE_POS_Y_DELTA,x dec SPRITE_CHAR_POS_Y,x ; if delta resets, we've crossed a character border rts
MoveSpriteDown
For the subroutine MoveSpriteDown we increase the variable (SPRITE_POS_Y) and store it in the variable (VIC_SPRITE_Y_POS). Then we increase the variable (SPRITE_POS_Y_DELTA) to manage the Sprite’s Y delta position and check to see it it reached an “8” and reset the Sprite’s Y delta to zero by storing the results in the variable (SPRITE_POS_Y_DELTA) . Finally we increase the variable (SPRITE_CHAR_POS_Y) since we crossed a character boundary.
;=================================================================================================== ; Much the same ; X = number of hardware sprite to move ;--------------------------------------------------------------------------------------------------- inc SPRITE_POS_Y,x ; increment the y pos variable for this sprite txa asl tay lda SPRITE_POS_Y,x sta VIC_SPRITE_Y_POS,y inc SPRITE_POS_Y_DELTA,x lda SPRITE_POS_Y_DELTA,x cmp #$08 beq @reset_delta rts
@reset_delta
lda #$00 sta SPRITE_POS_Y_DELTA,x inc SPRITE_CHAR_POS_Y,x rts
SpriteToCharPos
In the subroutine SpriteToCharPos we first check the variable value of (BIT_TABLE), flip all bits to “1”. However, if any bit is set to 1, it will become zero which can handle the Sprite moving to the left. Then we mask out the X extend bits for this Sprite so that no “unnecessary” 1 bits remain. These results are then stored in the variable (SPRITE_POS_X_EXTEND) and (VIC_SPRITE_X_EXTEND).
The next step is to check the X parameter within the variable (PARAM1) and store the results in the variable (SPRITE_CHAR_POS_X). We then check to see if a “30” alue exists here to see if we need to set the extended bit.
If it’s less than 30 then we don’t have to set it. Otherwise we check the variable (BIT_TABLE) again, set the X extend values to see if the correct bit is selected. Then the results are stored in the variable (SPRITE_POS_X_EXTEND) and (VIC_SPRITE_X_EXTEND), which handles the MSB X Sprite register.
;=================================================================================================== ; SPRITE TO CHAR POS ;=================================================================================================== ; Puts a sprite at the position of character X Y. Calculates the proper sprite coords from the ; screen memory position then sets it there directly. ; The primary use of this is the initial positioning of any sprite as it will align it with the ; proper delta set up. ; ; PARAM 1 = Character x pos (column) ; PARAM 2 = Character y pos (row) ; X = sprite number ;--------------------------------------------------------------------------------------------------- lda BIT_TABLE,x ; Lookup the bit for this sprite number (0-7) eor #$ff ; flip all bits (invert the byte %0001 would become %1110) and SPRITE_POS_X_EXTEND ; mask out the X extend bit for this sprite sta SPRITE_POS_X_EXTEND ; store the result back - we've erased just this sprites bit sta VIC_SPRITE_X_EXTEND ; store this in the VIC register for extended X bits lda PARAM1 ; load the X pos in character coords (the column) sta SPRITE_CHAR_POS_X,x ; store it in the character X position variable cmp #30 ; if X is less than 30, no need set the extended bit bcc @noExtendedX
lda BIT_TABLE,x ; look up the the bit for this sprite number ora SPRITE_POS_X_EXTEND ; OR in the X extend values - we have set the correct bit sta SPRITE_POS_X_EXTEND ; Store the results back in the X extend variable sta VIC_SPRITE_X_EXTEND ; and the VIC X extend register
In this area we get the Sprite number, multiply it by 2 and store it in the Y register. Then we check the variable (PARAM1) which contains the X character position, multiply the value by 8, add 24 to it and subtract the variable (SPRITE_DELTA_OFFSET_X) from it. Essentially this adds the edge of the screen to our Sprite’s X position and takes off the Sprite’s X delta offset to center the character position within the Sprite to align them very equally. The results are then stored in the variable (SPRITE_POS_X) and (VIC_SPRITE_X_POS) which places the Sprite on the screen.
@noExtendedX
; Setup our Y register so we transfer X/Y values to the ; correct VIC register for this sprite txa ; first, transfer the sprite number to A asl ; multiply it by 2 (shift left) tay ; then store it in Y ; (note : see how VIC sprite pos registers are ordered ; to understand why I'm doing this) lda PARAM1 ; load in the X Char position asl ; 3 x shift left = multiplication by 8 asl asl clc adc #24 - SPRITE_DELTA_OFFSET_X ; add the edge of screen (24) minus the delta offset ; to the rough center 8 pixels (1 char) of the sprite sta SPRITE_POS_X,x ; save in the correct sprite pos x variable sta VIC_SPRITE_X_POS,y ; save in the correct VIC sprite pos register
Next we get the variable (PARAM2) which manages the Y character position and store it in the variable (SPRITE_CHAR_Y_POS). Then we multiply the value by 3, add 50 to it and subtract the variable (SPRITE_DELTA_OFFSSET_Y). This adds the top edge of the screen and shaves off the Sprite’s Y delta values to align the character to the Sprite vertically. The result is then saved in the variable (SPRITE_POS_Y) and (VIC_SPRITE_Y_POS). Finally the delta X values are reset within the variable (SPRITE_POS_X_DELTA) and (SPRITE_POS_Y_DELTA).
lda PARAM2 ; load in the y char position (rows) "9" sta SPRITE_CHAR_POS_Y,x ; store it in the character y pos for this sprite asl ; 3 x shift left = multiplication by 8 asl asl clc adc #50 - SPRITE_DELTA_OFFSET_Y ; add top edge of screen (50) minus the delta offset - 42 sta SPRITE_POS_Y,x ; store in the correct sprite pos y variable sta VIC_SPRITE_Y_POS,y ; and the correct VIC sprite pos register lda #0 sta SPRITE_POS_X_DELTA,x ; set both x and y delta values to 0 - we are aligned sta SPRITE_POS_Y_DELTA,x ; on a character border (for the purposes of collisions) rts
AnimateSprite
First in the subroutine AnimateSprite let’s check the variable (SPRITE_ANIM_PLAY). If it is not yet at zero then we can continue this routine.
The animation continue here and we start off checking the variable (SPRITE_ANIM_TIMER). Again, we are checking to see if the value is at zero, which will exit or otherwise we continue on.
@timerCheck
We are not at zero yet, so let’s take the result in the accumulator and mask out the upper half byte (bits 0-3), then clear the variable (TIMER) result with a mask. If it’s at zero then we can skip out to the next step.
;===================================================================================================
; ANIMATE SPRITE
;---------------------------------------------------------------------------------------------------
; Animate an individual sprite. Taking data from it's Anim List, updating it's variables
; and updating it's animation frame
;
; It can currently handle loop, play once, and ping-pong animations
;
; X = sprite number to animate ; ; Modifies : Y, ZEROPAGE_POINTER_1
;
;---------------------------------------------------------------------------------------------------
; First - do we need to animate this sprite at all? Check the TIMER
lda SPRITE_ANIM_PLAY ; return if anim paused
bne @start
rts
@start
lda SPRITE_ANIM_TIMER,x ; load the anim timer mask
bne @timerCheck ; is our timer turned off? (set to 0)
rts
@timerCheck
and #%00001111 ; mask out the upper half byte (extra info)
and TIMER ; and the mask against the timer
beq @update ; if the result isn't 0 - return
rts
Now we take the contents of the variable (SPRITE_ANIM_TIMER) and store it in ZEROPAGE_POINTER_1. Then we load a result from the variable (SPRITE_ANIMATION + 1) high byte and save it in the high byte of ZEROPAGE_POINTER_1 + 1.
After this we check the variable (SPRITE_ANIM_TIMER). If the result is over zero then we count down the timer. Otherwise we decrement the variable (SPRITE_ANIM_COUNT). Keep going back until the timer is at zero
@update
;-------------------------------------------------------------------------
; First we need to fetch this sprites anim list. txa
; put the sprite number in A asl
; multiply by 2 (to lookup a word) tay
; store the result in Y lda SPRITE_ANIMATION,y
; fetch the address to the sprites Anim List
sta ZEROPAGE_POINTER_1 ; and store it in ZEROPAGE_POINTER_1
lda SPRITE_ANIMATION + 1,y
sta ZEROPAGE_POINTER_1 + 1 ;-------------------------------------------------------------------------
; Next - increment (or decrement for PING PONG) the animation counter
lda SPRITE_ANIM_TIMER,x ; check for the MSB in the timer, if it's set
bpl @incTimer ; we count down instead
dec SPRITE_ANIM_COUNT,x ; decrement anim counter and continue as normal
jmp @zerocheck
Increment the variable (SPRITE_ANIM_COUNT).
For this section we check the variable (SPRITE_ANIM_COUNT). If it’s at zero then we reset the “pong” value.
Get the value into the Y register and read from ZEROPAGE_POINTER_1. If we are still over zero then we can set the Sprite Image.
Otherwise compare the result in “TYPE_LOOP”. If there is a match then we reset this loop.
The next condition will check “TYPE_PING_PONG”. If it’s also at zero then we reset the “ping”.
Finally we clear the result and save it in the variable (SPRITE_ANIM_TIMER) and set value of “255” into (SPRITE_ANIM_COUNT).
@incTimer
inc SPRITE_ANIM_COUNT,x ; increment the counter
@zerocheck
lda SPRITE_ANIM_COUNT,x ; fetch it so we can do an end test
beq @resetPong ; it should NEVER be zero, unless it's a PING_PONG
; anim returning back to zero as the first bytes
; is the anim timer mask
tay ; use as an index to load the current frame from the
lda (ZEROPAGE_POINTER_1),y ; animlist
bpl @setImage
; Test to make sure the frame is positive (0-128)
; if it isn't, and the MSB is set, then it's the ; end byte, which we use to tell us the type of
; anim (and what to do when we reach the end)
cmp #TYPE_LOOP ; Check to see what type of anim this is
beq @resetLoop
cmp #TYPE_PING_PONG
beq @resetPing ;----------------------------------------------------------PLAY_ONCE_ANIM
; PlayOnce Anim doesn't get reset
lda #0 ; We set the anim timer to 0, so it never updates
sta SPRITE_ANIM_TIMER,x
lda #$FF ; We set the count to -1 ($FF) as something our
sta SPRITE_ANIM_COUNT,x ; code can check to see if a once only is finished
rts ;------------------------------------------------------PING_PONG_ANIM
; We've reached the end of the animlist
Get the variable result in (SPRITE_ANIM_TIMER), flip bit 7 to reset a timer which turns on decrementing. Save this result in the variable (SPRITE_ANIM_TIMER). Next load the variable (SPRITE_ANIM_COUNT), subtract 2 from it and store the result in (SPRITE_ANIM_COUNT). Now we check the variable value of (ZEROPAGE_POINTER_1),y and go set the Sprite Image.
@resetPing
lda SPRITE_ANIM_TIMER,x
eor #%10000000 ; flip bit 7 in the timer to start 0 check
; and turn on decrementing
sta SPRITE_ANIM_TIMER,x ; save the new counter
lda SPRITE_ANIM_COUNT,x
sec
sbc #2 ; subtract 2 from the anim counter
sta SPRITE_ANIM_COUNT,x ; and save the result
tay
lda (ZEROPAGE_POINTER_1),y ; lookup the new sprite frame
; A now has the sprite image
; X has the sprite number
; so we set the image(s)
jmp @setImage
Read the variable value of (SPRITE_ANIM_TIMER), flip bit 7 to count it in a forward direction and save the answer in the variable (SPRITE_ANIM_TIMER).
Next put a “2” in the variable (SPRITE_ANIM_COUNT) and read from (ZEROPAGE_POINTER_1),y once again.
Set the variable (SPRITE_ANIM_COUNT) to “1” and load again the result from (ZEROPAGE_POINTER_1),y.
@resetPong
; The reverse of the above
lda SPRITE_ANIM_TIMER,x
eor #%10000000 ; flip bit 7 (MSB) to count forwards
sta SPRITE_ANIM_TIMER,x ; save the new timer
lda #2 ; skip to frame 2
sta SPRITE_ANIM_COUNT,x ; save the new counter
tay
lda (ZEROPAGE_POINTER_1),y ; load the new sprite image
jmp @setImage ;-------------------------------------------------------------LOOP_ANIM
@resetLoop
lda #1 ; reset the counter to the first frame
sta SPRITE_ANIM_COUNT,x tay ; now fetch the first frame
lda (ZEROPAGE_POINTER_1),y
Now get ready to set the Sprite Image by calling the subroutine (SetSpriteImage). If X is “0” it’s the Player Sprite, so set a second sprite. Check X for a “2” for the “Enemy” sprite (not yet implemented).
For @secondSprite add 1 to the Sprite frame, add 1 to the Sprite number, call the subroutine (SetSpriteImage) and reduce the X register.
@setImage
;-------------------------------------------------------------------
; Set the sprite to it's new image - A currently contains the count
; ZEROPAGE_POINTER_1 has the address of the sprites animlist
; A = correct sprite image, X = sprite number,
; so we're ready to set our new sprite image
jsr SetSpriteImage ; placed in SPRITE_POINTER_BASE (register 2040+)
cpx #0 ; if sprite is 0 , it's the player sprite
beq @setSecondSprite ; so we need to set a second sprite
cpx #2 ; if sprite is 0 , it's the player sprite
beq @setSecondSprite ; so we need to set a second sprite
rts
@setSecondSprite
clc
adc #1 ; add one to the frame
inx ; add one to the sprite number
jsr SetSpriteImage
dex
rts
SetSpriteImage
Save the content received here onto the stack, add the Sprite Base. Store the results in (SPRITE_POINTER_BASE1) and (SPRITE_POINTER_BASE2).
;===================================================================================================
; SET SPRITE IMAGE
;===================================================================================================
; Sets the sprite image for a hardware sprite, and sets up its pointers for both screens
;---------------------------------------------------------------------------------------------------
; A = Sprite image number
; X = Hardware sprite
;
; Leaves registers intact
;---------------------------------------------------------------------------------------------------
pha
clc
adc #SPRITE_BASE ; Sprite image = image num + base
sta SPRITE_POINTER_BASE1,x
sta SPRITE_POINTER_BASE2,x
; sta SPRITE_POINTER_BASE3,x
pla
rts
InitSpriteAnim
Place a “1” in the variable (SPRITE_ANIM_COUNT), multiply it by 2 (to index a word). Then check ZEROAPGE_POINTER_1 (low and high bytes) and save the results in (SPRITE_ANIMATION – low and high bytes).
Now we begin a new Y loop. Get the value in ZEROPAGE_POINTER_1 and save it in the variable (SPRITE_ANIM_TIMER). Increase through the animation frames. Retrieve the value in ZEROPAGE_POINTER_1, set the sprite image with a call to (SetSpriteImage). Check for Sprite “0” or Sprite “1” and increase through each frame.
;=================================================================================================== ; INIT SPRITE ANIM ;--------------------------------------------------------------------------------------------------- ; ; Setup and initialize a sprites animations ; ; X = Sprite number ; ZERO_PAGE_POINTER_1 = animation list address ; ; Modifies A,Y ;--------------------------------------------------------------------------------------------------- lda #1 ; Reset Anim counter to first frame sta SPRITE_ANIM_COUNT,x txa ; copy sprite number to A asl ; multiply it by 2 (so we can index a word) tay ; transfer result to Y ; reads "ANIM_PLAYER_" or "ANIM_ENEMY_" lda ZEROPAGE_POINTER_1 ; Store the address for the animlist sta SPRITE_ANIMATION,y ; in the correct 'slot' for this sprite lda ZEROPAGE_POINTER_1 + 1 sta SPRITE_ANIMATION + 1,y ; SPRITE_ANIMATION = "ANIM_PLAYER_" (example) ldy #0 ; First byte in the list is the timer lda (ZEROPAGE_POINTER_1),y ; fetch it sta SPRITE_ANIM_TIMER,x ; store it in this sprites timer slot iny ; increment Y to 1 - the first anim frame lda (ZEROPAGE_POINTER_1),y ; load it ; right now we have the sprite image in A ; and the sprite number in X, which is exactly what ; what we need to use SetSpriteImage jsr SetSpriteImage cpx #0 ; if the sprite = 0, then we are setting the player sprite beq @secondSprite ; the player uses 2 sprites rts
@secondSprite
; We don't need to set all the info for this sprite inx ; increment X to the next hardware sprite clc ; add one to the current anim frame number adc #1 ; because our background sprite is the next frame. jsr SetSpriteImage ; Now set the sprite image rts
; SPRITE POINTER TABLES
;---------------------------------------------------------------------------------------------------
; Lookup tables for setting Sprite Pointers for the
; correct screens
SPRITE_POINTER_BASE1 = SCREEN1_MEM + $3f8
SPRITE_POINTER_BASE2 = SCREEN2_MEM + $3f8
SPRITE_POINTER_BASE3 = SCREEN2_MEM + $3f8
;===================================================================================================
; SPRITE HANDLING DATA
;===================================================================================================
; Sprite 0: ldx #0: ldx #1
; Sprite 0: (swimmer) ldx #2: ldx #3
; Sprite 1: (enemy) ldx #4: ldx #5
; byte 1: Sprite 1(19), byte 2: Sprite 2:(19)
SPRITE_STACK_X
byte 19,19,20,20,19,19 ;Handles the upper/lower sprite Y positions ; NOTE: This was originally managed by PARAM2 ; But with 2 different Y positions, it had to ; byte 1: Sprite 1(10), byte 2: Sprite 2:(12) ; be altered.
SPRITE_STACK_Y
byte 0,2,22,22,9,11 ; Handles the upper/lower sprite Y positions ; NOTE: This was originally managed by PARAM2 ; But with 2 different Y positions, it had to ; be altered.
SPRITE_DEPTH
byte 36
SPRITE_POS_Y_ADJUST
byte 0
PARAM2_SAVE
byte 0,0,0,0,0,0,0,0
SPRITE_IS_ACTIVE
byte $00,$00,$00,$00,$00,$00,$00,$00 ; Hardware sprite X position SPRITE_POS_X byte $00,$00,$00,$00,$00,$00,$00,$00 ; Delta X position (0-7) - within a char SPRITE_POS_X_DELTA byte $00,$00,$00,$00,$00,$00,$00,$00 SPRITE_CHAR_POS_X ; Char pos X - sprite position in character byte $00,$00,$00,$00,$00,$00,$00,$00 ; coords (0-40)
SPRITE_DELTA_TRIM_X
byte $00,$00,$00,$00,$00,$00,$00,$00 ; Trim delta for better collisions SPRITE_POS_X_EXTEND ; extended flag for X positon > 255 byte $00 ; bits 0-7 correspond to sprite numbers SPRITE_POS_Y ; Hardware sprite Y position byte $00,$00,$00,$00,$00,$00,$00,$00 SPRITE_POS_Y_DELTA byte $00,$00,$00,$00,$00,$00,$00,$00 SPRITE_CHAR_POS_Y byte $00,$00,$00,$00,$00,$00,$00,$00 SPRITE_DIRECTION_X byte $00,$00,$00,$00,$00,$00,$00,$00 ; Direction of the sprite (-1 0 1) SPRITE_DIRECTION_Y byte $00,$00,$00,$00,$00,$00,$00,$00 SPRITE_ANIM_TIMER byte $00,$00,$00,$00,$00,$00,$00,$00 ; Timing and playback direction for current anim SPRITE_ANIM_COUNT byte $00,$00,$00,$00,$00,$00,$00,$00 ; Position in the anim list SPRITE_ANIM_PLAY byte $00,$00,$00,$00,$00,$00,$00,$00 ; Currently animated or paused? (TO DO - single byte and use BIT_TABLE) ; Pointer to current animation table SPRITE_ANIMATION word $0000,$0000,$0000,$0000 word $0000,$0000,$0000,$0000 ; Enemy Data
ENEMY_SPRITE_POS_X
byte $00,$00,$00,$00,$00,$00,$00,$00 ; Delta X position (0-7) - within a char ENEMY_SPRITE_POS_X_DELTA byte $00,$00,$00,$00,$00,$00,$00,$00 ENEMY_SPRITE_CHAR_POS_X ; Char pos X - sprite position in character byte $00,$00,$00,$00,$00,$00,$00,$00 ; coords (0-40) ENEMY_SPRITE_DELTA_TRIM_X byte $00,$00,$00,$00,$00,$00,$00,$00 ; Trim delta for better collisions ENEMY_SPRITE_POS_X_EXTEND ; extended flag for X positon > 255 byte $00 ; bits 0-7 correspond to sprite numbers ENEMY_SPRITE_POS_Y ; Hardware sprite Y position byte $00,$00,$00,$00,$00,$00,$00,$00 ENEMY_SPRITE_POS_Y_DELTA byte $00,$00,$00,$00,$00,$00,$00,$00 ENEMY_SPRITE_CHAR_POS_Y byte $00,$00,$00,$00,$00,$00,$00,$00
;===================================================================================================
; SPRITE ANIMATION TABLES
;===================================================================================================
; Anims are held in a block of data containing info and a list of anim frames. ; byte 0 = Timing mask:
; The lower 4 bits contain a mask we will and with the master timer, if the result is ; is 0 we will go to the next frame
; valid values are those that use all bits (1,3,5,7,15) .
; Bit 7 is used for the direction of the animation (in ping pong anims). if we set it
; we can then use bmi (Branch MInus) to see if we count backwards instead of forwards
;
; byte 1 to end = sprite numbers for the animation frames
;
; The last byte both terminates the animation, and also shows what should be done at the end
; of it. On a loop we would reset to 0, on a play once anim we would end, on a ping pong type
; it will start counting backwards
;---------------------------------------------------------------------------------------------------
;---------------------------------------------------------
; ANIMATION TYPES
TYPE_LOOP = $
FF
TYPE_PLAY_ONCE = $FE
TYPE_PING_PONG = $FD
;---------------------------------------------------------
ANIM_TEST
; numbers 0 to 9
byte %00001111
byte 40,41,42,43,44,45,46,47,48,49
byte TYPE_PING_PONG
ANIM_PLAYER_WALK_R
; 7 frame animation walk right
byte %0000111
byte 18,20,22
byte TYPE_LOOP
ANIM_PLAYER_WALK_L
byte %0000111
byte 12,14,16
byte TYPE_LOOP
ANIM_PLAYER_IDLE
; Player idle animation
byte %0001111
byte 4,2
byte TYPE_PING_PONG
ANIM_PLAYER_FALL
byte %0001111
byte 34
byte TYPE_PLAY_ONCE
; Animation that shows as Player climbs the rope up/down
ANIM_CLIMB_ROPE_UP
byte %0000011
byte 8,10,12
byte TYPE_LOOP
ANIM_PLAYER_JUMP
; Player jump animation
byte %00000111
byte 2,4,6
byte TYPE_PING_PONG
ANIM_PLAYER_PUNCH_R
byte %0001111
byte 24,26
byte TYPE_LOOP
ANIM_PLAYER_PUNCH_L
byte %0001111
byte 30,32
byte TYPE_LOOP
ANIM_PLAYER_KICK_R
byte %0001111
byte 34,36
byte TYPE_LOOP
ANIM_PLAYER_KICK_L
byte %0001111
byte 38,40
byte TYPE_LOOP
PLAYER_JUMPCOUNT
byte 0
; ENEMY ANIMATION
ANIM_ENEMY_IDLE ; Player idle animation
byte %0001111
byte 58,60
byte TYPE_PING_PONG
ANIM_ENEMY_WALK_R
; 7 frame animation walk right
byte %0000011
byte 74,76,78
byte TYPE_LOOP
ANIM_ENEMY_WALK_L
byte %0000111
byte 72,74
byte TYPE_LOOP
ANIM_ENEMY_CLIMB_ROPE
byte %0000011
byte 60,62
byte TYPE_LOOP
ANIM_PLAYER_SWIM_R
byte %0000011
byte 43,45
byte TYPE_LOOP
ANIM_PLAYER_SWIM_L
byte %0000011
byte 46,48
byte TYPE_LOOP
Leave A Comment