Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .include "macro_math.s"
- .export _reset_all_particles, _update_particles, _spawn_particle
- .export _spawn_brick_smash_particle_system, _spawn_coin_particle_system
- ; ca65 helper routines
- .import decsp3, shlax4, shrax4, shlaxy
- ; variables defined in C but needed in this code.
- .import _cam
- ; CONSTANTS
- NUM_PARTICLES = 16
- PART_GRAVITY_DEFAULT = 56 ;((255*22)/100)
- INDEX_NONE = $ff
- COIN_VEL = ((4 << 8) + 128) ; based on C version
- PART_TYPE_NONE = 0
- PART_TYPE_ROCK = 1
- PART_TYPE_COIN = 2
- ; NOTE: this doesn't need to be saved, but that's where the spare memory is.
- .segment "XRAM"
- part_x_scr: .res NUM_PARTICLES
- part_x_pix: .res NUM_PARTICLES
- part_x_sub: .res NUM_PARTICLES
- part_x_vel_pix: .res NUM_PARTICLES
- part_x_vel_sub: .res NUM_PARTICLES
- part_y_pix: .res NUM_PARTICLES
- part_y_sub: .res NUM_PARTICLES
- part_y_vel_pix: .res NUM_PARTICLES
- part_y_vel_sub: .res NUM_PARTICLES
- part_tile: .res NUM_PARTICLES
- part_counter: .res NUM_PARTICLES
- part_type: .res NUM_PARTICLES
- part_state: .res NUM_PARTICLES
- part_x_reg_temp: .res 1
- ; routine params
- in_part_x_h: .res 1
- _in_part_x_h = in_part_x_h ; alias with a _
- .export _in_part_x_h
- in_part_x_l: .res 1
- _in_part_x_l = in_part_x_l
- .export _in_part_x_l
- in_part_y_h: .res 1
- _in_part_y_h = in_part_y_h
- .export _in_part_y_h
- .segment "BANK3"
- ;;-----------------------------------------------------------------------
- .proc _reset_all_particles
- ldx #(NUM_PARTICLES-1)
- lda #0
- loop:
- jsr _clear_particle
- dex
- bpl loop
- rts
- .endproc
- ;;-----------------------------------------------------------------------
- .proc _update_particles
- ldx #(NUM_PARTICLES-1)
- loop:
- ; is the particle alive?
- lda part_state, x
- bne :+
- jmp next_particle
- :
- ;
- ; move
- ;
- ; add x velocity to x position
- add24xs16 part_x_sub, part_x_pix, part_x_scr, part_x_vel_sub, part_x_vel_pix
- ; y velocity
- add16x8const part_y_vel_sub, part_y_vel_pix, #PART_GRAVITY_DEFAULT
- ; add y velocity to y position
- add16x16 part_y_sub, part_y_pix, part_y_vel_sub, part_y_vel_pix
- ; custom update
- lda part_type,x
- ; ROCK
- cmp #PART_TYPE_ROCK
- bne :+
- ; custom rock logic
- clc
- lda part_counter,x
- cmp #30
- bne end_custom_update
- ; change tile half way
- inc part_tile,x
- jmp end_custom_update
- ; COIN
- : cmp #PART_TYPE_COIN
- bne :+
- ; custom coin logic
- ; 0xf0 + ((tick_count >> 2) % 4)
- lda part_counter,x
- lsr
- lsr
- and #%00000011 ; %4
- clc
- adc #$f0
- sta part_tile,x
- jmp end_custom_update
- :
- end_custom_update:
- ; did the particle fall off the bottom?
- lda part_y_pix,x
- clc
- cmp #208
- bcc :+
- ; off the bottom
- lda #0
- sta part_state,x
- jmp next_particle
- :
- dec part_counter,x
- bne :+
- ; counter has expired. Disable particle.
- lda #0
- sta part_state,x
- jmp next_particle
- :
- ;
- ; draw
- ;
- jsr _clip_and_draw_particle
- next_particle:
- dex
- bmi :+
- jmp loop
- :
- rts
- .endproc ; _update_particles
- ;;-----------------------------------------------------------------------
- ; params: x - particle index
- ;
- .proc _clear_particle
- lda #0
- sta part_x_scr, x
- sta part_x_pix, x
- sta part_x_sub, x
- sta part_x_vel_pix, x
- sta part_x_vel_sub, x
- sta part_y_pix, x
- sta part_y_sub, x
- sta part_y_vel_pix, x
- sta part_y_vel_sub, x
- sta part_tile, x
- sta part_counter, x
- sta part_type, x
- sta part_state, x
- rts
- .endproc ; _clear_partcile
- ;;-----------------------------------------------------------------------
- ; params: x reg - offset into particles
- ; output: x reg - the index of the next free particle.
- .proc _find_next_free_particle
- loop:
- ; is the particle alive?
- lda part_state, x
- bne next_particle
- ; particle is alive, so just return with X pointing
- ; to this index
- rts
- next_particle:
- dex
- bpl loop
- ; if we reach this point X will be $ff, which is INDEX_NONE
- rts
- .endproc ;_find_next_free_particle
- ;;-----------------------------------------------------------------------
- brick_smash_y_vel_pix:
- .byte $fc, $fc, $fe, $fe ; -4, -4, -2, -2
- ; both are 128, but one is negative and the other is positive.
- brick_smash_x_vel_h:
- .byte $ff, 0, $ff, 0 ; -128, 128, -128, 128
- brick_smash_x_offset:
- .byte 0, 8, 0, 8
- brick_smash_y_offset:
- .byte 0, 0, 8, 8
- ; params: in_part_x_l - x position in pixels
- ; in_part_x_h - x position in sreen pages
- ; in_part_y_h - y position in pixels
- .proc _spawn_brick_smash_particle_system
- ldx #(NUM_PARTICLES-1)
- .repeat 4, I
- jsr _find_next_free_particle
- cpx #INDEX_NONE
- bne :+
- rts
- : jsr _clear_particle
- ; bring the particle to life
- lda #1
- sta part_state, x
- clc
- lda in_part_x_l
- adc brick_smash_x_offset+I
- sta part_x_pix, x
- lda in_part_x_h
- sta part_x_scr, x
- clc
- lda in_part_y_h
- adc brick_smash_y_offset+I
- sta part_y_pix, x
- ; always 128 sub pixel, but the pix value will
- ; determine if it is negative or positive.
- lda #128
- sta part_x_vel_sub,x
- lda brick_smash_x_vel_h+I
- sta part_x_vel_pix,x
- lda brick_smash_y_vel_pix+I
- sta part_y_vel_pix,x
- lda #$e0
- sta part_tile,x
- ; live for about 1 second
- lda #60
- sta part_counter,x
- lda #PART_TYPE_ROCK
- sta part_type,x
- .endrepeat
- rts
- .endproc ;_spawn_brick_smash_particle_system
- ;;-----------------------------------------------------------------------
- ; params: in_part_x_l - x position in pixels
- ; in_part_x_h - x position in sreen pages
- ; in_part_y_h - y position in pixels
- .proc _spawn_coin_particle_system
- ldx #(NUM_PARTICLES-1)
- jsr _find_next_free_particle
- cpx #INDEX_NONE
- bne :+
- rts
- : jsr _clear_particle
- ; bring the particle to life
- lda #1
- sta part_state, x
- lda in_part_x_l
- sta part_x_pix, x
- lda in_part_x_h
- sta part_x_scr, x
- lda in_part_y_h
- sta part_y_pix, x
- lda #<(-COIN_VEL)
- sta part_y_vel_sub,x
- lda #>(-COIN_VEL)
- sta part_y_vel_pix,x
- lda #$f0
- sta part_tile,x
- ; live for about 1/2 second
- lda #32
- sta part_counter,x
- lda #PART_TYPE_COIN
- sta part_type,x
- rts
- .endproc ;_spawn_coin_particle_system
- ;;-----------------------------------------------------------------------
- ;unused
- .proc _spawn_particle
- ldx #(NUM_PARTICLES-1)
- loop:
- ; is the particle alive?
- lda part_state, x
- bne next_particle
- ; particle is alive
- ; start with a blank slate so that we only need to update
- ; the values that change.
- jsr _clear_particle
- ; bring the particle to life
- lda #1
- sta part_state, x
- lda #128
- sta part_x_pix, x
- sta part_y_pix, x
- lda #128
- sta part_x_vel_pix,x
- jmp done
- next_particle:
- dex
- bpl loop
- done:
- rts
- .endproc ;_spawn_particle
- ;;-----------------------------------------------------------------------
- ; params: x - particle index
- ;
- .proc _clip_and_draw_particle
- stx part_x_reg_temp
- ; offscreen left clipping
- lda part_x_scr,x
- cmp _cam+1
- beq :+ ; equal, continue check
- bcc remove ; a < cam
- jmp test_right_clip
- : lda part_x_pix,x
- cmp _cam
- bcc remove ; a < cam
- test_right_clip:
- ; offscreen right clipping
- lda _cam+1
- clc
- adc #1
- cmp part_x_scr,x
- beq :+ ; equal, continue check
- bcc done ; cam < obj
- jmp @draw_sprite
- : lda part_x_pix,x
- cmp _cam
- bcs done
- @draw_sprite:
- ; oam_spr(64, 64, 0, 0);
- jsr decsp3
- ; camera shift
- sec
- lda part_x_pix,x
- sbc _cam ; pos_x low
- ldy #$02 ; number of stack params
- sta (sp),y
- lda part_y_pix,x ; param 2 - y
- sec
- sbc #1 ; pixel offset
- dey
- sta (sp),y
- lda part_tile,x ; param 3 - chr
- dey
- sta (sp),y
- lda #02 ; 03 param 4 goes into a reg - attr
- ; stomp x
- jsr _oam_spr
- ; restore the x reg
- ldx part_x_reg_temp
- done:
- rts
- remove:
- lda #0
- sta part_state, x
- rts
- .endproc ; _clip_and_draw_particle
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement