dos33fsprogs/pt3_player/fire.s

365 lines
6.9 KiB
ArmAsm
Raw Normal View History

; Lo-res fire animation, size-optimized
; by deater (Vince Weaver) <vince@deater.net>
; based on code described here http://fabiensanglard.net/doom_fire_psx/
FIRE_YSIZE=20
2019-05-17 18:02:13 +00:00
;=======================
; fire_init
;=======================
; call at beginning to clear out framebuffer
fire_init:
lda #<fire_framebuffer
sta FIRE_FB_L
lda #>fire_framebuffer
sta FIRE_FB_H
ldx #FIRE_YSIZE
clear_fire_loop:
lda #0
2019-05-16 17:03:33 +00:00
ldy #39
clear_fire_line_loop:
sta (FIRE_FB_L),Y
dey
2019-05-16 17:03:33 +00:00
bpl clear_fire_line_loop
done_fire_line_loop:
clc
lda FIRE_FB_L
adc #40
sta FIRE_FB_L
2019-06-01 03:55:01 +00:00
bcc skip_inc_hi
inc FIRE_FB_H
skip_inc_hi:
dex
bne clear_fire_loop
lda #7
2019-06-01 05:49:16 +00:00
;fall through
;jsr fire_setline
2019-06-01 05:49:16 +00:00
;rts
;======================================
; set bottom line to color in A
;======================================
2019-05-17 18:02:13 +00:00
; Set to 7 to init, Set to 0 to have fire go out
fire_setline:
ldx #<(fire_framebuffer+(FIRE_YSIZE-1)*40)
stx FIRE_FB_L
ldx #>(fire_framebuffer+(FIRE_YSIZE-1)*40)
stx FIRE_FB_H
ldy #39
set_fire_line:
sta (FIRE_FB_L),Y
dey
bpl set_fire_line
done_set_fire_line:
rts
;===============================
;===============================
; Draw fire frame
;===============================
;===============================
draw_fire_frame:
;===============================
; Update fire frame
;===============================
2019-05-17 18:19:18 +00:00
; Unroll x 2
2019-05-17 18:02:13 +00:00
; set up working line (to store to)
2019-05-16 17:37:21 +00:00
lda #<fire_framebuffer ; 2
2019-05-16 18:58:13 +00:00
sta fire_smc5_fb+1 ; 4
2019-05-16 17:37:21 +00:00
lda #>fire_framebuffer ; 2
2019-05-16 18:58:13 +00:00
sta fire_smc5_fb+2 ; 4
2019-05-16 16:47:04 +00:00
2019-05-17 18:02:13 +00:00
; set up input line, one below, (to load from)
2019-05-16 17:37:21 +00:00
lda #<(fire_framebuffer+40) ; 2
2019-05-16 18:58:13 +00:00
sta fire_smc5_fb2+1 ; 4
2019-05-16 17:37:21 +00:00
lda #>(fire_framebuffer+40) ; 2
2019-05-16 18:58:13 +00:00
sta fire_smc5_fb2+2 ; 4
2019-05-16 16:47:04 +00:00
2019-05-17 18:02:13 +00:00
; loop X (ypos) from 0 - FIRE_YSIZE-1
ldx #0 ; 2
2019-05-16 16:47:04 +00:00
fire_fb_update:
2019-05-16 18:45:25 +00:00
; FIXME: optimize
; original = ??? (complex)
2019-05-17 18:55:53 +00:00
; TODO: unroll once and combine with the lores copy on even lines?
2019-05-16 18:45:25 +00:00
2019-05-17 18:55:53 +00:00
; Loop Y (xpos) from 39 to 0
2019-05-17 18:02:13 +00:00
ldy #39 ; 2
2019-05-16 16:47:04 +00:00
fire_fb_update_loop:
2019-05-16 17:37:21 +00:00
; Get random 16-bit number
jsr random16 ; 40
2019-06-01 05:49:16 +00:00
; A randomly has either SEEDL or SEEDH here, I guess that's enough?
2019-05-17 18:02:13 +00:00
; get random number Q 0..3
; Q used to see if whether we grab same lower value or if decrement
2019-05-16 18:45:25 +00:00
and #$3 ; 2
sta FIRE_Q ; 3
; 0..12 = A volume, 13-25 = B volume, 26-39 = C volume
2019-05-16 17:37:21 +00:00
lda A_VOLUME ; 3
2019-05-16 18:45:25 +00:00
cpy #13 ; 2
bcc fire_vol ; blt ; 2/3
2019-05-16 17:37:21 +00:00
lda B_VOLUME ; 3
2019-05-16 18:45:25 +00:00
cpy #26 ; 2
bcc fire_vol ; blt ; 2/3
2019-05-16 17:37:21 +00:00
lda C_VOLUME ; 3
fire_vol:
and #$f ; 2
; adjust fire height with volume
2019-05-16 18:45:25 +00:00
cmp #$8 ; 2
bcs fire_medium ; bge ; 2/3
2019-05-16 17:37:21 +00:00
fire_low:
; Q=1 3/4 of time
2019-05-16 18:45:25 +00:00
lda FIRE_Q ; 3
2019-05-17 18:19:18 +00:00
bne fire_one ; 0-3, is not 0 3/4 of time ; 2/3
2019-06-01 03:55:01 +00:00
beq fire_set ; 3
2019-05-16 17:37:21 +00:00
fire_medium:
2019-05-16 18:45:25 +00:00
cmp #$d ; 2
2019-06-01 03:55:01 +00:00
lda FIRE_Q ; 3
2019-05-17 18:19:18 +00:00
bcs fire_high ; bge ; 2/3
2019-05-16 17:37:21 +00:00
; Q=1 1/2 of time
2019-05-16 18:45:25 +00:00
and #$1 ; 2
2019-06-01 03:55:01 +00:00
bcc fire_set ; branch always ; 3
2019-05-16 17:37:21 +00:00
fire_high:
; Q=1 1/4 of time
2019-06-01 03:55:01 +00:00
;;lda FIRE_Q ; is 0 1/4 of time ; 3
2019-05-17 18:19:18 +00:00
bne fire_zero ; 2/3
fire_one:
lda #1 ; 2
bne fire_set ; 3
fire_zero:
2019-05-16 18:45:25 +00:00
lda #0 ; 2
2019-05-17 18:19:18 +00:00
fire_set:
2019-05-16 18:45:25 +00:00
sta FIRE_Q ; 3
2019-05-16 17:03:33 +00:00
2019-05-17 18:19:18 +00:00
2019-05-17 18:55:53 +00:00
;=================
; check if flame from left/right
2019-05-17 18:19:18 +00:00
2019-05-17 18:55:53 +00:00
; store Y as we over-write it
2019-05-16 18:45:25 +00:00
sty FIRE_Y ; 3
2019-05-16 17:37:21 +00:00
2019-05-16 18:58:13 +00:00
; bounds check
2019-05-17 18:55:53 +00:00
; on edges, don't wrap
2019-05-16 18:58:13 +00:00
2019-06-01 03:55:01 +00:00
tya ; 2
2019-05-16 18:45:25 +00:00
beq fire_r_same ; 2/3
cpy #39 ; 2
beq fire_r_same ; 2/3
2019-05-17 18:19:18 +00:00
; RAND_R
; 50% chance fire comes from below
; 25% chance comes from right
; 25% change comes from left
2019-05-16 18:45:25 +00:00
lda SEEDH ; 3
2019-06-01 03:55:01 +00:00
lsr ; 2
2019-05-16 18:45:25 +00:00
and #$1 ; 2
2019-06-01 03:55:01 +00:00
bne fire_r_same ; 2/3
bcc r_up ; 2/3
2019-05-16 17:37:21 +00:00
r_down:
2019-05-16 18:45:25 +00:00
dey ; 2
2019-06-01 03:55:01 +00:00
.byte $a9 ; 2
2019-05-16 17:37:21 +00:00
r_up:
2019-05-16 18:45:25 +00:00
iny ; 2
2019-05-16 17:37:21 +00:00
fire_r_same:
2019-05-16 16:47:04 +00:00
; get next line color
2019-05-16 18:58:13 +00:00
fire_smc5_fb2:
lda $1234,Y ; 4+
2019-05-16 16:47:04 +00:00
2019-05-17 18:55:53 +00:00
; restore saved Y
2019-05-16 18:45:25 +00:00
ldy FIRE_Y ; 3
2019-05-16 17:37:21 +00:00
2019-05-17 18:19:18 +00:00
; have value, subtract Q
2019-05-16 18:45:25 +00:00
sec ; 2
sbc FIRE_Q ; 3
2019-05-16 16:47:04 +00:00
; saturate to 0
2019-05-16 18:45:25 +00:00
bpl fb_positive ; 2/3
lda #0 ; 2
2019-05-16 16:47:04 +00:00
fb_positive:
; store out
2019-05-16 18:58:13 +00:00
fire_smc5_fb:
sta $1234,Y ; store out ; 5
2019-05-16 16:47:04 +00:00
2019-05-16 18:45:25 +00:00
dey ; 2
bpl fire_fb_update_loop ; 2/3
2019-05-16 16:47:04 +00:00
done_fire_fb_update_loop:
2019-05-17 18:02:13 +00:00
; if just finished odd line, we are already set up
; to do the framebuffer copy for the prev two lines?
2019-05-16 16:47:04 +00:00
; complicated adjustment
2019-05-16 18:45:25 +00:00
clc ; 2
2019-05-16 18:58:13 +00:00
lda fire_smc5_fb+1 ; 4
2019-05-16 18:45:25 +00:00
adc #40 ; 2
2019-05-16 18:58:13 +00:00
sta fire_smc5_fb+1 ; 4
2019-06-01 03:55:01 +00:00
bcc skip_fb_inc1 ; 2/3
inc fire_smc5_fb+2 ; 4
clc ; 2
2019-06-01 03:55:01 +00:00
skip_fb_inc1:
2019-05-16 18:58:13 +00:00
lda fire_smc5_fb2+1 ; 4
2019-05-16 18:45:25 +00:00
adc #40 ; 2
2019-05-16 18:58:13 +00:00
sta fire_smc5_fb2+1 ; 4
2019-06-01 03:55:01 +00:00
bcc skip_fb2_inc1 ; 2/3
inc fire_smc5_fb2+2 ; 4
skip_fb2_inc1:
2019-05-16 16:47:04 +00:00
2019-05-16 18:45:25 +00:00
inx ; 2
cpx #(FIRE_YSIZE-1) ; 2
2019-06-01 05:49:16 +00:00
;beq fire_update_done ; 2/3
bne fire_fb_update ; 3
2019-05-16 16:47:04 +00:00
2019-05-16 17:37:21 +00:00
fire_update_done:
2019-05-16 16:47:04 +00:00
2019-05-17 18:02:13 +00:00
;===================================
; copy framebuffer to low-res screen
2019-05-17 18:02:13 +00:00
;===================================
2019-05-16 17:50:27 +00:00
lda #<fire_framebuffer ; 2
sta fire_smc_fb+1 ; 5
lda #<(fire_framebuffer+40) ; 2
sta fire_smc_fb2+1 ; 5
2019-06-01 03:55:01 +00:00
lda #>fire_framebuffer ; 2
sta fire_smc_fb+2 ; 5
;this lda could be omitted if values match
2019-05-16 17:50:27 +00:00
lda #>(fire_framebuffer+40) ; 2
sta fire_smc_fb2+2 ; 5
2019-05-16 17:50:27 +00:00
lda #16 ; 2
sta FIRE_FB_LINE ; 3
2019-05-16 17:50:27 +00:00
ldx #(FIRE_YSIZE/2) ; 2
fire_fb_copy:
2019-05-16 17:50:27 +00:00
ldy FIRE_FB_LINE ; 3
iny ; 2
iny ; 2
sty FIRE_FB_LINE ; 3
; Set up output, self-modifying code
2019-05-16 17:50:27 +00:00
lda gr_offsets,Y ; 4+
sta fire_smc_outl+1 ; 4
2019-05-16 17:50:27 +00:00
lda gr_offsets+1,Y ; 4+
clc ; 2
adc DRAW_PAGE ; 3
sta fire_smc_outl+2 ; 4
; FIXME: below, can we do this better?
; 50: original code
; 39: move to big lookup table
; 33: move save/restore X outside inner loop
; 30: self-modifying code
2019-05-16 17:50:27 +00:00
ldy #39 ; 2
stx FIRE_X ; 3
fire_fb_copy_loop:
; get top byte
; note, seems backwards, apple II LORES bottom byte is on top
fire_smc_fb2:
lda $1234,Y ; 4+
asl ; 2
asl ; 2
asl ; 2
; get bottom byte
fire_smc_fb:
ora $1234,Y ; 4+
2019-05-16 17:50:27 +00:00
tax ; 2
lda fire_colors,X ; 4+
fire_smc_outl:
sta $1234,Y ; store out ; 5
2019-05-16 17:50:27 +00:00
dey ; 2
bpl fire_fb_copy_loop ; 2/3
done_fire_fb_copy_loop:
ldx FIRE_X ; 3
; complicated adjustment
2019-05-16 17:50:27 +00:00
clc ; 2
lda fire_smc_fb+1 ; 4
2019-05-16 17:50:27 +00:00
adc #80 ; 2
sta fire_smc_fb+1 ; 5
2019-06-01 03:55:01 +00:00
bcc skip_fb_inc2 ; 2/3
inc fire_smc_fb+2 ; 5
clc ; 2
2019-06-01 03:55:01 +00:00
skip_fb_inc2:
lda fire_smc_fb2+1 ; 4
2019-05-16 17:50:27 +00:00
adc #80 ; 2
sta fire_smc_fb2+1 ; 5
2019-06-01 03:55:01 +00:00
bcc skip_fb2_inc2 ; 2/3
inc fire_smc_fb2+2 ; 5
skip_fb2_inc2:
2019-05-16 17:50:27 +00:00
dex ; 2
bne fire_fb_copy ; 2/3
2019-05-16 17:50:27 +00:00
rts ; 6
;fire_colors_low: .byte $00,$00,$03,$02,$06,$07,$0E,$0F
;fire_colors_high: .byte $00,$00,$30,$20,$60,$70,$E0,$F0
fire_colors:
; 0 1 2 3 4 5 6 7
; 0 0 3 2 6 7 e f
.byte $00,$00,$03,$02,$06,$07,$0e,$0f ; 0
.byte $00,$00,$03,$02,$06,$07,$0e,$0f ; 0
.byte $30,$30,$33,$32,$36,$37,$3e,$3f ; 3
.byte $20,$20,$23,$22,$26,$27,$2e,$2f ; 2
.byte $60,$60,$63,$62,$66,$67,$6e,$6f ; 6
.byte $70,$70,$73,$72,$76,$77,$7e,$7f ; 7
.byte $e0,$e0,$e3,$e2,$e6,$e7,$ee,$ef ; e
.byte $f0,$f0,$f3,$f2,$f6,$f7,$fe,$ff ; f
; FIXME: just reserve space in our memory map
fire_framebuffer:
.res 40*FIRE_YSIZE, $00