Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .proc RunPlayer
- jsr UpdateStatus
- jsr HandlePlayer
- rts
- .endproc
- NOVA_ACCEL_SPEED = 2
- NOVA_DECEL_SPEED = 4
- NOVA_WALK_SPEED = 2
- NOVA_RUN_SPEED = 4
- .proc UpdateStatus
- HealthX = 0
- HealthCount = 1
- ldy OamPtr
- lda #15
- sta HealthX
- sta OAM_YPOS+(4*0),y
- sta OAM_YPOS+(4*1),y
- sta OAM_XPOS+(4*0),y
- sta OAM_XPOS+(4*2),y
- lda #15+8
- sta OAM_YPOS+(4*2),y
- sta OAM_YPOS+(4*3),y
- sta OAM_XPOS+(4*1),y
- sta OAM_XPOS+(4*3),y
- lda #$4c
- sta OAM_TILE+(4*0),y
- lda #$4d
- sta OAM_TILE+(4*2),y
- lda #$4e
- sta OAM_TILE+(4*1),y
- lda #$4f
- sta OAM_TILE+(4*3),y
- lda #OAM_COLOR_0
- sta OAM_ATTR+(4*0),y
- sta OAM_ATTR+(4*1),y
- sta OAM_ATTR+(4*2),y
- sta OAM_ATTR+(4*3),y
- tya
- add #4*4
- tay
- ; Draw all hearts needed
- lda PlayerHealth
- lsr
- php
- sta HealthCount
- Loop:
- lda HealthCount
- beq NoMoreHearts
- lda #$4a
- jsr MakeHeart
- dec HealthCount
- bne Loop
- NoMoreHearts:
- plp ; add a half heart if needed
- bcc :+
- lda #$4b
- jsr MakeHeart
- :
- sty OamPtr
- rts
- MakeHeart:
- sta OAM_TILE,y
- lda HealthX
- sta OAM_XPOS,y
- add #8
- sta HealthX
- lda #0
- sta OAM_ATTR,y
- lda #15+16
- sta OAM_YPOS,y
- iny
- iny
- iny
- iny
- rts
- .endproc
- .proc HandlePlayer
- ;OldPlayerPYL = 0
- ;OldPlayerPYH = 1
- Temp = 1
- BlockUL = 2
- BlockUR = 3
- BlockLL = 4
- BlockLR = 5
- FourCorners = 6
- BottomCMP = 7
- SkipFourCorners = 8
- MaxSpeedLeft = 9
- MaxSpeedRight = 10
- lda #0
- sta PlayerOnGround
- sta FourCorners
- sta SkipFourCorners
- lda PlayerWasRunning ; nonzero = B button, only updated when on ground
- beq :+
- lda #-NOVA_RUN_SPEED*16
- sta MaxSpeedLeft
- lda #NOVA_RUN_SPEED*16
- sta MaxSpeedRight
- bne NotWalkSpeed
- : lda #-NOVA_WALK_SPEED*16
- sta MaxSpeedLeft
- lda #NOVA_WALK_SPEED*16
- sta MaxSpeedRight
- NotWalkSpeed:
- ; lda PlayerPYL
- ; sta OldPlayerPYL
- ; lda PlayerPYH
- ; sta OldPlayerPYH
- lda PlayerVYH
- bmi GravityAddOK
- lda PlayerVYL
- cmp #$60
- bcs SkipGravity
- GravityAddOK:
- lda PlayerVYL
- add #4
- sta PlayerVYL
- bcc SkipGravity
- inc PlayerVYH
- SkipGravity:
- ; apply gravity
- lda PlayerPYL
- add PlayerVYL
- sta PlayerPYL
- lda PlayerPYH
- adc PlayerVYH
- and #$0f
- sta PlayerPYH
- lda PlayerJumpCancelLock
- beq :+
- dec PlayerJumpCancelLock
- :
- lda PlayerWalkLock
- beq :+
- dec PlayerWalkLock
- :
- lda PlayerInvincible
- beq :+
- dec PlayerInvincible
- :
- lda PlayerTailAttack
- beq NoTail
- inc PlayerTailAttack
- lda PlayerTailAttack
- cmp #6 ; launch attack
- bne :+
- jsr DoTailAttack
- :
- lda PlayerTailAttack
- cmp #14
- bcc :+
- lda #0
- sta PlayerTailAttack
- :
- jmp SkipTail
- NoTail:
- lda keylast
- and #KEY_B|KEY_LEFT|KEY_RIGHT
- bne :+
- lda keydown
- and #KEY_B
- beq :+
- lda #SFX::TAIL_WHOOSH
- jsr PlaySound
- inc PlayerTailAttack
- :
- SkipTail:
- lda PlayerVYH
- bpl :+
- lda keydown ; cancel a jump
- and #KEY_A
- bne :+
- lda PlayerJumpCancelLock
- bne :+
- lda #0
- sta PlayerVYH
- sta PlayerVYL
- :
- lda PlayerWalkLock
- bne NotWalk
- ; handle left and right
- lda keydown
- and #KEY_LEFT
- beq NotLeft
- ldy #0
- sty PlayerDownTimer
- iny
- sty PlayerDir
- lda PlayerVXL
- cmp MaxSpeedLeft ; can be either run speed or walk speed
- beq NotLeft
- cmp #-NOVA_RUN_SPEED*16
- beq NotLeft
- lda PlayerVXL
- bne :+
- dec PlayerVXH
- : sub #NOVA_ACCEL_SPEED
- sta PlayerVXL
- NotLeft:
- lda keydown
- and #KEY_DOWN
- beq NotDown
- lda PlayerDownTimer
- cmp #60
- bcs YesDown
- inc PlayerDownTimer
- bne YesDown
- NotDown:
- lda #0
- sta PlayerDownTimer
- YesDown:
- lda keydown
- and #KEY_RIGHT
- beq NotRight
- lda #0
- sta PlayerDownTimer
- sta PlayerDir
- lda PlayerVXL
- cmp MaxSpeedRight ; can be either run speed or walk speed
- beq NotRight
- cmp #NOVA_RUN_SPEED*16
- beq NotRight
- lda PlayerVXL
- add #NOVA_ACCEL_SPEED
- sta PlayerVXL
- bne NotRight
- inc PlayerVXH
- NotRight:
- NotWalk:
- lda #NOVA_DECEL_SPEED ; adjust the deceleration speed if you're trying to turn around
- sta Temp
- .if 1
- lda keydown
- and #KEY_LEFT
- beq :+
- lda PlayerVXH
- bmi IsMoving
- lsr Temp
- :
- lda keydown
- and #KEY_RIGHT
- beq :+
- lda PlayerVXL
- ora PlayerVXH
- beq Stopped
- lda PlayerVXH
- bpl IsMoving
- lsr Temp
- :
- .endif
- ; lda keydown
- ; and #KEY_LEFT|KEY_RIGHT
- ; bne IsMoving
- lda PlayerVXL
- ora PlayerVXH
- beq IsMoving
- lda PlayerVXH ; if negative, make positive
- and #128
- sta 0
- beq :+
- neg16 PlayerVXL, PlayerVXH
- :
- lda PlayerVXL
- sub Temp ;#NOVA_DECEL_SPEED
- sta PlayerVXL
- bcs @NotCarry
- dec PlayerVXH
- bpl @NotCarry
- lda #0
- sta PlayerVXH
- sta PlayerVXL
- @NotCarry:
- lda 0 ; if it was negative make negative again
- beq :+
- neg16 PlayerVXL, PlayerVXH
- :
- Stopped:
- IsMoving:
- ; fix walk speed if we just came out of a run
- lda PlayerVXL
- bit PlayerVXH
- bpl :+
- neg
- :
- cmp MaxSpeedRight
- beq NoFixWalkSpeed
- bcc NoFixWalkSpeed
- sub #NOVA_DECEL_SPEED
- bit PlayerVXH
- bpl :+
- neg
- :
- sta PlayerVXL
- NoFixWalkSpeed:
- ; apply speed without caring if it's gonna push us into a wall or not
- lda PlayerPXL
- add PlayerVXL
- sta PlayerPXL
- lda PlayerPXH
- adc PlayerVXH
- sta PlayerPXH
- ; ------- FOUR CORNER COLLISION DETECTION -------
- ; http://pineight.com/mw/index.php?title=Four-corner_collision_detection
- lda #M_SOLID_ALL
- sta BottomCMP
- lda PlayerVYH
- bmi :+
- lda #0
- sta PlayerJumping
- lda #M_SOLID_TOP
- sta BottomCMP
- :
- ; check blocks in the middle
- ; TODO: make less dumb
- lda PlayerPYL
- add #<(16*16)
- lda PlayerPYH
- adc #>(16*16)
- tay
- lda #$40
- add PlayerPXL
- lda PlayerPXH
- adc #0
- jsr GetLevelColumnPtr
- cmp #Metatiles::COIN
- bne NotCoin
- lda #0
- jsr ChangeBlock
- lda #SFX::COIN
- jsr PlaySound
- jsr AddCoin
- jmp DoneCheckMiddle
- NotCoin:
- cmp #Metatiles::SPRING
- bne NotSpring
- lda #-1
- sta PlayerVYH
- lda #-$70
- sta PlayerVYL
- lda #30
- sta PlayerJumpCancelLock
- lda #SFX::SPRING
- jsr PlaySoundDebounce
- inc SkipFourCorners
- NotSpring:
- DoneCheckMiddle:
- ; top
- lda PlayerPYL
- add #<(8*16)
- lda PlayerPYH
- adc #>(8*16)
- tay
- lda #0
- pha
- add PlayerPXL ; left side
- lda PlayerPXH
- adc #0
- jsr GetLevelColumnPtr
- sta BlockUL
- tax
- lda MetatileFlags,x
- cmp #$80
- rol FourCorners
- pla
- add #$70
- add PlayerPXL ; right side
- lda PlayerPXH
- adc #0
- jsr GetLevelColumnPtr
- sta BlockUR
- tax
- lda MetatileFlags,x
- cmp #$80
- rol FourCorners
- ;bottom
- lda PlayerPYL
- add #<(24*16)
- lda PlayerPYH
- adc #>(24*16)
- tay
- lda #0 ; left side
- pha
- add PlayerPXL ; left side
- lda PlayerPXH
- adc #0
- jsr GetLevelColumnPtr
- sta BlockLL
- tax
- lda MetatileFlags,x
- cmp BottomCMP
- rol FourCorners
- pla
- add #$70
- add PlayerPXL ; right side
- lda PlayerPXH
- adc #0
- jsr GetLevelColumnPtr
- sta BlockLR
- tax
- lda MetatileFlags,x
- cmp BottomCMP
- rol FourCorners
- lda SkipFourCorners
- beq :+
- rts
- :
- ; now call the right routine
- ldx FourCorners
- lda FourCornersH,x
- pha
- lda FourCornersL,x
- pha
- rts
- HSpeedDirectionOffset:
- .byt $8f, 0
- FourCornersL:
- .byt <(FC_____ -1), <(FC____R -1)
- .byt <(FC___L_ -1), <(FC___LR -1)
- .byt <(FC__R__ -1), <(FC__R_R -1)
- .byt <(FC__RL_ -1), <(FC__RLR -1)
- .byt <(FC_L___ -1), <(FC_L__R -1)
- .byt <(FC_L_L_ -1), <(FC_L_LR -1)
- .byt <(FC_LR__ -1), <(FC_LR_R -1)
- .byt <(FC_LRL_ -1), <(FC_LRLR -1)
- FourCornersH:
- .byt >(FC_____ -1), >(FC____R -1)
- .byt >(FC___L_ -1), >(FC___LR -1)
- .byt >(FC__R__ -1), >(FC__R_R -1)
- .byt >(FC__RL_ -1), >(FC__RLR -1)
- .byt >(FC_L___ -1), >(FC_L__R -1)
- .byt >(FC_L_L_ -1), >(FC_L_LR -1)
- .byt >(FC_LR__ -1), >(FC_LR_R -1)
- .byt >(FC_LRL_ -1), >(FC_LRLR -1)
- FC_____:
- FC__RL_:
- FC_L__R:
- FC_LR_R:
- FC_LRL_:
- rts
- FC_LRLR:
- lda PlayerPYL
- sub #$a0
- sta PlayerPYL
- subcarry PlayerPYH
- lda #0
- sta PlayerVYL
- sta PlayerVYH
- rts
- FC_L_LR:
- jsr FC___LR
- jmp FC_L_L_
- FC__RLR:
- jsr FC___LR
- jmp FC__R_R
- FC__R_R:
- lda #0
- sta PlayerVXL
- sta PlayerVXH
- lda #$8f
- sta PlayerPXL
- lda BlockUR
- cmp #Metatiles::GROUND_CLIMB_L
- bne :+
- DoClimb:
- lda #-1
- sta PlayerVYH
- lda #-$40
- sta PlayerVYL
- lda #10
- sta PlayerJumpCancelLock
- lsr
- sta PlayerWalkLock
- : rts
- FC_L_L_:
- lda #0
- sta PlayerVXL
- sta PlayerVXH
- sta PlayerPXL
- inc PlayerPXH
- lda BlockUL
- cmp #Metatiles::GROUND_CLIMB_R
- beq DoClimb
- rts
- FC_L___:
- lda PlayerPXL
- add #$40
- sta PlayerPXL
- addcarry PlayerPXH
- rts
- FC__R__:
- lda PlayerPXL
- sub #$40
- sta PlayerPXL
- subcarry PlayerPXH
- rts
- FC_LR__:
- lda #0
- sta PlayerVYH
- sta PlayerVYL
- ; check the block we bumped into
- lda PlayerPYH
- tay
- lda #$40
- add PlayerPXL
- lda PlayerPXH
- adc #0
- jsr GetLevelColumnPtr
- cmp #Metatiles::BRICKS
- beq BreakBricks
- cmp #Metatiles::PRIZE
- beq OpenPrize
- lda #SFX::BUMP
- jmp PlaySoundDebounce
- OpenPrize: ; insert effects here
- lda #Metatiles::USED_PRIZE
- jsr ChangeBlock
- lda #SFX::COIN
- jsr PlaySoundDebounce
- jsr AddCoin
- rts
- BreakBricks: ; insert effects here
- lda #Metatiles::EMPTY
- jsr ChangeBlock
- lda #SFX::SMASH
- jsr PlaySoundDebounce
- rts
- FC___L_:
- FC____R:
- FC___LR:
- ldx BlockLL
- lda MetatileFlags,x
- ldx BlockLR
- cmp MetatileFlags,x
- bne NotFallthrough
- and #~M_POST_PROCESS
- cmp #M_SOLID_TOP|M_FALLABLE_LEDGE
- bne NotFallthrough
- lda PlayerDownTimer
- cmp #15
- bcc NotFallthrough
- rts
- NotFallthrough:
- inc PlayerOnGround
- lda keydown
- and #KEY_B
- sta PlayerWasRunning
- lda #0
- sta PlayerVYH
- sta PlayerVYL
- lda #$80
- sta PlayerPYL
- lda keylast
- and #KEY_A
- bne :+
- lda keydown
- and #KEY_A
- beq :+
- lda #<(-$50)
- sta PlayerVYL
- lda #>(-$50)
- sta PlayerVYH
- inc PlayerJumping
- lda #SFX::JUMP
- jsr PlaySound
- :
- rts
- .endproc
- .proc DisplayPlayer
- DrawX = 0
- DrawY = 1
- Attrib = 2
- MiddleOffsetX = 3
- DrawX2 = 4
- ; need to do this first even if we skip the drawing, because of PlayerDrawX and PlayerDrawY
- RealPosToScreenPos PlayerPXL, PlayerPXH, ScrollX, DrawX
- RealPosToScreenPos PlayerPYL, PlayerPYH, ScrollY, DrawY
- ; copy to PlayerDrawX and PlayerDrawY which are used for collision detection
- lda DrawX
- sta PlayerDrawX
- lda DrawY
- sta PlayerDrawY
- ; if the player's invincible, flicker their sprite
- lda PlayerInvincible
- and #1
- beq :+
- rts
- :
- ; okay now we want to actually draw the player
- lda #0
- sta MiddleOffsetX
- sta Attrib
- sta PlayerTiles+6
- sta PlayerAnimationFrame
- lda PlayerTailAttack
- beq :+
- tax
- lda TailAttackFrame,x
- sta PlayerAnimationFrame
- :
- lda PlayerAnimationFrame
- beq NormalFrame
- tay
- lda #$0f
- sta PlayerTiles+0
- lda #$01
- sta PlayerTiles+1
- lda AnimO,y
- ldx PlayerDir
- beq :+
- neg
- : sta MiddleOffsetX
- lda Anim0,y
- sta PlayerTiles+2
- lda Anim1,y
- sta PlayerTiles+3
- lda Anim2,y
- sta PlayerTiles+4
- lda Anim3,y
- sta PlayerTiles+5
- lda Anim4,y
- sta PlayerTiles+6
- jmp NoSpecialAnimation
- NormalFrame:
- ldy #$00
- sty PlayerTiles+0
- iny
- sty PlayerTiles+1
- iny
- sty PlayerTiles+2
- iny
- sty PlayerTiles+3
- iny
- sty PlayerTiles+4
- iny
- sty PlayerTiles+5
- EndAnimationFrame:
- lda PlayerJumping
- beq :+
- lda #$0c
- sta PlayerTiles+3
- lda #$08
- sta PlayerTiles+4
- lda #$09
- sta PlayerTiles+5
- jmp NoSpecialAnimation
- :
- lda PlayerOnGround
- beq :+
- lda PlayerDir
- sta PlayerDirForScroll
- :
- lda PlayerOnGround
- bne :+
- lda #$0d
- sta PlayerTiles+2
- lda #$0e
- sta PlayerTiles+3
- lda #$0a
- sta PlayerTiles+4
- lda #$0b
- sta PlayerTiles+5
- jmp NoSpecialAnimation
- :
- ; animate walking
- lda PlayerVXL
- ora PlayerVXH
- beq :+
- lda retraces
- and #%100
- beq :+
- lda #$06
- sta PlayerTiles+4
- lda #$07
- sta PlayerTiles+5
- :
- NoSpecialAnimation:
- ; flip horizontally
- lda PlayerDir
- beq :+
- lda #OAM_XFLIP
- sta Attrib
- swapy PlayerTiles+0, PlayerTiles+1
- swapy PlayerTiles+2, PlayerTiles+3
- swapy PlayerTiles+4, PlayerTiles+5
- :
- lda PlayerDir
- bne :+
- lda DrawX
- sub #8
- sta DrawX
- :
- lda DrawX
- sta DrawX2
- ldx OamPtr
- ldy #0 ; current sprite
- PutSprite:
- lda PlayerTiles,y
- sta OAM_TILE,x
- lda DrawX
- add XPosList,y
- sta OAM_XPOS,x
- lda DrawY
- add YPosList,y
- sta OAM_YPOS,x
- cpy #1
- bne :+
- lda DrawX
- add MiddleOffsetX
- sta DrawX
- :
- lda Attrib
- sta OAM_ATTR,x
- inx
- inx
- inx
- inx
- iny
- cpy #6
- bne PutSprite
- stx OamPtr
- lda PlayerTiles+6
- beq NoExtraTile
- sta OAM_TILE,x
- ldy PlayerDir
- lda DrawX
- add ExtraTileX,y
- sta OAM_XPOS,x
- lda DrawY
- add #16
- sta OAM_YPOS,x
- lda Attrib
- sta OAM_ATTR,x
- inx
- inx
- inx
- inx
- stx OamPtr
- NoExtraTile:
- lda CoinShowTimer
- beq NoCoinShow
- dec CoinShowTimer
- lda PlayerDrawY
- sub #12
- sta OAM_YPOS+(4*0),x
- sta OAM_YPOS+(4*1),x
- sta OAM_YPOS+(4*2),x
- sta OAM_YPOS+(4*3),x
- lda DrawX2
- sub #8
- sta OAM_XPOS+(4*0),x
- add #8
- sta OAM_XPOS+(4*1),x
- add #8
- sta OAM_XPOS+(4*2),x
- add #8
- sta OAM_XPOS+(4*3),x
- lda #0
- sta OAM_ATTR+(4*0),x
- sta OAM_ATTR+(4*1),x
- sta OAM_ATTR+(4*2),x
- sta OAM_ATTR+(4*3),x
- ldy Coins+0
- lda BCD99,y
- pha
- .repeat 4
- lsr
- .endrep
- add #$40
- sta OAM_TILE+(4*2),x
- pla
- and #$0f
- add #$40
- sta OAM_TILE+(4*3),x
- ldy Coins+1
- lda BCD99,y
- pha
- .repeat 4
- lsr
- .endrep
- add #$40
- sta OAM_TILE+(4*0),x
- pla
- and #$0f
- add #$40
- sta OAM_TILE+(4*1),x
- txa
- add #16
- sta OamPtr
- NoCoinShow:
- rts
- XPosList: .byt 0, 8, 0, 8, 0, 8
- YPosList: .byt 0, 0, 8, 8, 16, 16
- ExtraTileX: .byt 16, -8
- Anim0: .byt $02, $10, $13, $15, $19 ;$20
- Anim1: .byt $03, $11, $14, $16, $1a ;$21
- Anim2: .byt $04, $12, $12, $17, $1b ;$22
- Anim3: .byt $05, $05, $05, $18, $1c ;$23
- Anim4: .byt $00, $00, $00, $00, $1d ;$24
- AnimO: .byt 0, 0, 0, 2, 3 ; 4
- TailAttackFrame:
- .byt 1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1
- ; 00 01 | 0f 01 | 0f 01 | 0f 01 | 0f 01 | 0f 01
- ; 02 03 | 10 11 | 13 14 | 15 16 | 19 1a | 20 21
- ; 04 05 | 12 05 | 12 05 | 17 18 | 1b 1c 1d | 22 23 24
- .endproc
- .proc AdjustCamera
- LevelIndex = 0 ; index for (ScrollLevelPointer),y
- AttrIndex = 1
- Temp = 2
- ScrollOldX = 4
- LevelPointer2 = 6
- ScrollDifference = 6
- DrawX = Temp
- NewCameraX = Temp
- lda ScrollX+0
- sta ScrollOldX+0
- lda ScrollX+1
- sta ScrollOldX+1
- ; FOLLOW THE PLAYER
- .scope
- player_x = PlayerPXL
- player_xhi = PlayerPXH
- player_facing = PlayerDirForScroll
- camtarget_lo = Temp+0
- camtarget_hi = Temp+1
- camera_lo = ScrollX+0
- camera_hi = ScrollX+1
- ; Step 1: Find the position that the camera seeks.
- lda player_x
- sta camtarget_lo
- lda player_xhi
- ldy player_facing ; 0 for right, 1 for left
- sec
- sbc CameraTargetByFacing,y
- bcs :+
- lda #0
- sta camtarget_lo
- sec
- : sta camtarget_hi
- ; Step 2: Find the distance that the camera must move
- ; to reach this position.
- lda camtarget_lo
- sbc camera_lo
- sta camtarget_lo
- lda camtarget_hi
- sbc camera_hi
- ; and divide by 4 for smoothing
- cmp #$80
- ror a
- ror camtarget_lo
- cmp #$80
- ror a
- ror camtarget_lo
- sta camtarget_hi
- ; Step 3: Add this to produce the camera's new position.
- ; The bit shifted out of camtarget_lo into carry can be used
- ; for free
- lda camtarget_lo
- adc camera_lo
- sta camera_lo
- lda camtarget_hi
- adc camera_hi
- sta camera_hi
- .endscope
- .if 0
- ; Step 1: Find the position that the camera seeks.
- lda PlayerPXL
- sta NewCameraX
- lda PlayerPXH
- ldy PlayerDir
- sec
- sbc SubtractForDirections,y
- bcs :+
- lda #0
- sta NewCameraX
- sec
- : sta NewCameraX+1
- ; Step 2: Find the distance that the camera must move
- ; to reach this position.
- lda NewCameraX+0
- sbc ScrollX+0
- sta NewCameraX+0
- lda NewCameraX+1
- sbc ScrollX+1
- ; and divide by 4 for smoothing
- cmp #$80
- ror a
- ror NewCameraX+0
- cmp #$80
- ror a
- ror NewCameraX+0
- sta NewCameraX+1
- ; Step 3: Add this to produce the camera's new position.
- ; The bit shifted out of camtarget_lo into carry can be used
- ; for free
- lda NewCameraX+0
- adc ScrollX+0
- sta NewCameraX+0
- lda NewCameraX+1
- adc ScrollX+1
- sta NewCameraX+1
- .endif
- ; ----------------------------------------
- lda ScrollX+1
- eor ScrollOldX+1
- and #%10 ; need updates every 32 pixels
- bne :+
- ldx IsScrollUpdate
- beq _rts
- inc ThirtyUpdateAddr+1
- dex
- jeq UpdateScrollBufferRight
- dex
- jeq ScrollBuffer3
- dex
- jeq UpdateScrollBufferRight
- _rts:
- rts
- :
- lda ScrollX+1
- cmp ScrollOldX+1
- beq _rts
- bcs Right
- Left:
- lsr
- sub #2
- jmp FillIt
- Right:
- lsr
- add #10
- FillIt:
- sta ScrollUpdateChunk
- ; make level pointer
- ldy #0
- sty ScrollLevelPointer+1
- lda ScrollUpdateChunk
- .repeat 5
- asl
- rol ScrollLevelPointer+1
- .endrep
- sta ScrollLevelPointer
- ; setup second pointer
- lda ScrollLevelPointer+1
- ora #$60
- sta ScrollLevelPointer+1
- sta LevelPointer2+1
- lda ScrollLevelPointer
- add #16
- sta LevelPointer2
- ; make ThirtyUpdate address (low part)
- lda ScrollUpdateChunk
- and #7
- asl
- asl
- and #31
- sta ThirtyUpdateAddr+1
- ; high part
- lda ScrollUpdateChunk
- and #%1000 ; becomes 0 or 4
- lsr
- ora #$20
- sta ThirtyUpdateAddr+0
- ; fill ThirtyUpdate buffer
- jsr UpdateScrollBufferLeft
- ; fill attributes buffer
- ldy #0
- sty AttrIndex
- LoopAttr:
- lda (ScrollLevelPointer),y
- tax
- lda MetatilePalettes,x
- and #%00000011
- sta Temp
- lda (LevelPointer2),y
- tax
- lda MetatilePalettes,x
- and #%00001100
- ora Temp
- sta Temp
- iny
- lda (ScrollLevelPointer),y
- tax
- lda MetatilePalettes,x
- and #%00110000
- ora Temp
- sta Temp
- lda (LevelPointer2),y
- tax
- lda MetatilePalettes,x
- and #%11000000
- ora Temp
- iny
- ldx AttrIndex
- sta AttributeWriteD,x
- inx
- stx AttrIndex
- cpx #8
- bne LoopAttr
- ; make attribute addresses
- lda ScrollUpdateChunk
- and #7
- sta Temp
- ldx #3
- : lda AttributeAddrsLo,x
- ora Temp
- sta AttributeWriteA2,x
- dex
- bpl :-
- ; make high address
- lda ThirtyUpdateAddr+0
- ora #3
- sta AttributeWriteA1
- lda #4
- sta IsScrollUpdate
- rts
- AttributeAddrsLo:
- .byt $c0, $c8, $d0, $d8
- CameraTargetByFacing: ; 3/8 and 5/8
- .byt 8, 8 ;6, 10
- .endproc
- .proc ScrollBuffer3
- ; ---- also spawn any sprites we need to spawn ----
- jsr SpritePointerAdjust
- .if 0
- lda ScrollUpdateChunk
- asl
- sta 1 ; 1 = destination column
- ldy CurSpriteIndex
- lda SpriteListRAM,y ; current sprite X pos > destination?
- cmp 1
- beq No
- bcc Increase
- Decrease: ; yes, decrease it
- jsr SpritePointerDecrease
- jmp No
- Increase: ; no, increase it
- jsr SpritePointerIncrease
- No:
- .endif
- lda ScrollLevelPointer
- add #16
- sta ScrollLevelPointer
- jmp UpdateScrollBufferLeft
- .endproc
- .if 0 ; TODO: finish and make it faster than the one that iterates through the whole list
- .proc SpritePointerAdjust
- lda ScrollUpdateChunk
- asl
- sta 1
- ora #1
- sta 2
- ldy CurSpriteIndex ; don't try to the left if at the leftmost sprite
- beq DontTryLeft ; try going right instead
- lda SpriteListRAM-3,y
- cmp 1
- beq YesLeft
- cmp 2
- beq YesLeft
- DontTryLeft:
- lda SpriteListRAM,y ; don't try to the right if at the rightmost sprite
- cmp #255
- beq Exit ; exit if at the end of the list
- lda SpriteListRAM+3,y
- cmp 1
- beq YesRight
- cmp 2
- beq YesRight
- SaveAndExit:
- sty CurSpriteIndex
- Exit:
- rts
- YesLeft:
- dey
- dey
- dey
- jsr TryMakeSprite
- sty CurSpriteIndex
- rts
- YesRight:
- iny
- iny
- iny
- jsr TryMakeSprite
- sty CurSpriteIndex
- rts
- .endproc
- .endif
- .if 1
- .proc SpritePointerAdjust ; version that iterates through the ENTIRE list, but isn't buggy
- lda ScrollUpdateChunk
- asl
- sta 1
- ora #1
- sta 2
- ldy #0
- Loop:
- lda SpriteListRAM,y
- cmp #255
- beq Exit
- cmp 1
- beq Make
- cmp 2
- beq Make
- Next:
- iny
- iny
- iny
- bne Loop
- Make:
- jsr TryMakeSprite
- jmp Next
- Exit:
- rts
- .endproc
- .endif
- .if 0
- .proc SpritePointerDecrease ; buggy
- Loop:
- sty CurSpriteIndex
- jsr TryMakeSprite
- ldy CurSpriteIndex
- cpy #0
- beq Exit
- dey
- dey
- dey
- lda SpriteListRAM,y
- cmp 1
- bcs Exit
- bne Loop
- Exit:
- rts
- .endproc
- .proc SpritePointerIncrease ; buggy
- Loop:
- sty CurSpriteIndex
- jsr TryMakeSprite
- ldy CurSpriteIndex
- iny
- iny
- iny
- lda SpriteListRAM,y
- cmp #255
- beq Exit
- cmp 1
- bcs Exit
- bne Loop
- Exit:
- rts
- .endproc
- .endif
- .proc TryMakeSprite ; sprite at index Y in the sprite list
- sty 0
- ldx #0
- : lda ObjectF1,x ; if there's a sprite in that location
- beq :+
- lda ObjectIndexInLevel,x ; and it's spawned from this entry in the sprite list
- cmp 0
- beq AlreadyMade ; don't spawn it again
- : inx ; try next object slot
- cpx #ObjectLen
- bne :--
- beq NotAlreadyMade
- AlreadyMade:
- rts
- NotAlreadyMade: ; okay, go spawn the object
- jsr FindFreeObjectX
- bcs :+
- rts
- :
- lda SpriteListRAM,y ; get X
- sta ObjectPXH,x
- lda #0 ; clear stuff out
- sta ObjectF3,x
- sta ObjectF4,x
- sta ObjectTimer,x
- sta ObjectVXH,x
- sta ObjectVXL,x
- sta ObjectVYH,x
- sta ObjectVYL,x
- sta ObjectPXL,x
- sta ObjectPYL,x
- lda #ENEMY_STATE_INIT
- sta ObjectF2,x
- iny
- lda SpriteListRAM,y ; get Y and flags
- and #15
- sta ObjectPYH,x
- cmp SpriteListRAM,y ; check if Y = the Y+Flags byte; if so, no flags
- beq NoFlags
- lda SpriteListRAM,y
- lsr
- lsr
- lsr
- lsr
- sta ObjectF3,x
- and #%1000
- beq NoFlags ; if the high bit isn't set, not using extended flags
- tya ; save Y since we'll need it again right after
- pha
- lda ObjectF3,x ; get the 3 bits already written
- and #%0111 ; select them only
- sec ; add LastSpriteIndex+1 since at LastSpriteIndex it's the end of sprite list marker
- adc LastSpriteIndex
- tay
- lda SpriteListRAM,y
- sta ObjectF3,x
- pla
- tay
- NoFlags:
- iny
- lda SpriteListRAM,y ; get type and direction flag
- sta ObjectF1,x ; store
- ldy 0 ; restore Y to what it was
- tya
- sta ObjectIndexInLevel,x ; no "sty absolute,x" so transfer first
- rts
- .endproc
- .proc UpdateScrollBufferLeft
- LevelIndex = 0
- ldy #0
- LoopLeft:
- sty LevelIndex
- lda (ScrollLevelPointer),y
- tax
- tya
- asl ; Thirty index is LevelIndex * 2
- tay
- lda MetatileUL,x
- sta ThirtyUpdateTile+0,y
- lda MetatileLL,x
- sta ThirtyUpdateTile+1,y
- ldy LevelIndex
- iny
- cpy #15
- bne LoopLeft
- rts
- .endproc
- .proc UpdateScrollBufferRight
- LevelIndex = 0
- ldy #0
- LoopRight:
- sty LevelIndex
- lda (ScrollLevelPointer),y
- tax
- tya
- asl ; Thirty index is LevelIndex * 2
- tay
- lda MetatileUR,x
- sta ThirtyUpdateTile+0,y
- lda MetatileLR,x
- sta ThirtyUpdateTile+1,y
- ldy LevelIndex
- iny
- cpy #15
- bne LoopRight
- rts
- .endproc
- .proc AddCoin
- lda #60
- sta CoinShowTimer
- inc Coins
- lda Coins
- cmp #100
- bne :+
- lda #0
- sta Coins
- inc Coins+1
- lda Coins+1
- cmp #100
- bne :+
- lda #99
- sta Coins+1
- :
- rts
- .endproc
- .proc DoTailAttack
- lda PlayerAbility
- asl
- tax
- lda AbilityTable+1,x
- pha
- lda AbilityTable+0,x
- pha
- rts
- AbilityTable:
- .raddr AbilityNone
- .raddr AbilityBlaster
- .raddr AbilityGlider
- .raddr AbilityBomb
- .raddr AbilityFire
- .raddr AbilityFirework
- .raddr AbilityNice
- .raddr AbilityBoomerang
- .raddr AbilityBall
- .raddr AbilityWater
- .raddr AbilityFan
- .raddr AbilityBurger
- LimitObjectAmount:
- ; limits the number of projectiles to a given amount by aborting if it's already at the limit
- sta 0 ; 0 = limit
- ldx #0
- ldy #0 ; Y = counter for number of player projectiles
- : lda ObjectF1,x
- and #~1
- cmp #Enemy::PLAYER_PROJECTILE*2
- bne :+
- iny ; yes, this is a player projectile
- cpy 0
- bne :+
- pla ; abort
- pla
- rts
- : inx
- cpx #ObjectLen
- bne :--
- rts
- AbilityNone:
- ldy #PlayerProjectileType::STUN_STAR
- lda keydown
- and #KEY_UP
- beq :+
- ldy #PlayerProjectileType::COPY_ORB
- : tya
- jsr MakeShot
- bcc Exit
- lda #$20
- jsr SetXVelocity
- lda #20/4
- sta ObjectTimer,x
- Exit:
- rts
- AbilityBlaster:
- lda #PlayerProjectileType::BLASTER_SHOT
- jsr MakeShot
- bcc @Exit
- lda #$40
- jsr SetXVelocity
- lda #50/4
- sta ObjectTimer,x
- @Exit:
- rts
- AbilityGlider:
- lda #4
- jsr LimitObjectAmount
- lda #PlayerProjectileType::LIFE_GLIDER
- jsr MakeShot
- bcc @Exit
- lda keydown
- and #KEY_UP
- sta ObjectF3,x
- lda #140/4
- sta ObjectTimer,x
- @Exit:
- rts
- AbilityBomb:
- lda #2
- jsr LimitObjectAmount
- lda #PlayerProjectileType::BOMB
- jsr MakeShotWide
- bcc @Exit
- lda #200/4
- sta ObjectTimer,x
- lda keydown
- and #KEY_UP|KEY_DOWN
- sta ObjectF3,x
- and #KEY_UP
- beq :+
- lda #$20
- jsr SetXVelocity
- lda #-$40
- sta ObjectVYL,x
- lda #255
- sta ObjectVYH,x
- lsr ObjectTimer,x
- :
- @Exit:
- rts
- AbilityFire:
- lda #3
- jsr LimitObjectAmount
- lda #PlayerProjectileType::FIREBALL
- jsr MakeShotWide
- bcc @Exit
- lda #80/4
- sta ObjectTimer,x
- lda keydown
- and #KEY_UP
- beq :+
- lda #-$40
- sta ObjectVYL,x
- lda #255
- sta ObjectVYH,x
- : lda keydown
- and #KEY_DOWN
- bne :+
- lda #$20
- jsr SetXVelocity
- @Exit:
- : rts
- AbilityFirework:
- lda #1
- jsr LimitObjectAmount
- lda #PlayerProjectileType::FIREWORK_CURSOR
- jsr MakeShot
- bcc @Exit
- lda #120/4
- sta ObjectTimer,x
- lda #$10
- jsr SetXVelocity
- @Exit:
- rts
- AbilityNice:
- lda #1
- jsr LimitObjectAmount
- lda #PlayerProjectileType::ICE_BLOCK
- jsr MakeShotWide
- bcc @Exit
- lda #80/4
- sta ObjectTimer,x
- lda #$30
- jsr SetXVelocity
- @Exit:
- rts
- AbilityBoomerang:
- rts
- AbilityBall:
- lda #1
- jsr LimitObjectAmount
- lda #PlayerProjectileType::BALL
- jsr MakeShotWide
- bcc @Exit
- lda #80/4
- sta ObjectTimer,x
- lda #$30
- jsr SetXVelocity
- @Exit:
- rts
- AbilityWater:
- lda #PlayerProjectileType::WATER_BOTTLE
- jsr MakeShotWide
- bcc @Exit
- lda #48/4
- sta ObjectTimer,x
- lda keydown
- and #KEY_UP
- bne :+
- lda #$20
- jsr SetXVelocity
- : lda #-$40
- sta ObjectVYL,x
- lda #255
- sta ObjectVYH,x
- @Exit:
- rts
- AbilityFan:
- lda #3
- jsr LimitObjectAmount
- lda #PlayerProjectileType::TORNADO
- jsr MakeShotWide
- bcc @Exit
- lda #80/4
- sta ObjectTimer,x
- lda #$30
- jsr SetXVelocity
- @Exit:
- rts
- AbilityBurger:
- lda #2
- jsr LimitObjectAmount
- lda #PlayerProjectileType::BURGER
- jsr MakeShotWide
- bcc @Exit
- lda #80/4
- sta ObjectTimer,x
- lda #$30
- jsr SetXVelocity
- @Exit:
- rts
- SetXVelocity:
- sta ObjectVXL,x
- tay
- lda #0
- sta ObjectVXH,x
- tya
- ldy PlayerDir
- beq :+
- neg
- sta ObjectVXL,x
- lda #255
- sta ObjectVXH,x
- : rts
- MakeShotCommon:
- jsr ObjectClearX
- lda 0
- sta ObjectF2,x
- lda PlayerPYH
- adc #0
- sta ObjectPYH,x
- rts
- MakeShotWide:
- sta 0
- jsr FindFreeObjectX
- bcs :+
- clc
- rts
- : lda #Enemy::PLAYER_PROJECTILE*2
- sta ObjectF1,x
- jsr MakeShotCommon
- lda PlayerPYL
- add #8*16
- sta ObjectPYL,x
- ldy PlayerDir
- beq Right
- Left16Wide:
- lda PlayerPXL
- sta ObjectPXL,x
- lda PlayerPXH
- sub #1
- sta ObjectPXH,x
- sec
- rts
- MakeShot:
- sta 0
- jsr FindFreeObjectX
- bcs :+
- clc
- rts
- : lda PlayerDir
- ora #Enemy::PLAYER_PROJECTILE*2
- sta ObjectF1,x
- jsr MakeShotCommon
- lda PlayerPYL
- add #13*16
- sta ObjectPYL,x
- ldy PlayerDir
- beq Left
- Right:
- lda PlayerPXL
- add #$80
- sta ObjectPXL,x
- lda PlayerPXH
- adc #0
- sta ObjectPXH,x
- sec
- rts
- Left:
- lda PlayerPXL
- sub #8
- sta ObjectPXL,x
- lda PlayerPXH
- sbc #0
- sta ObjectPXH,x
- sec
- rts
- .endproc
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement