From 3a68c7d758440d8b66fce167449665d388c4ad6b Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Wed, 30 Dec 2020 18:25:43 -0500 Subject: [PATCH] tfv: split up mode7 code --- tfv/Makefile | 2 +- tfv/flying_mode7.s | 627 ++++++++++++++++++++++++++++++++++++++++ tfv/flying_sprites.inc | 58 ++++ tfv/tfv_flying.s | 630 +---------------------------------------- 4 files changed, 689 insertions(+), 628 deletions(-) create mode 100644 tfv/flying_mode7.s create mode 100644 tfv/flying_sprites.inc diff --git a/tfv/Makefile b/tfv/Makefile index ebe41ca6..644b8e2a 100644 --- a/tfv/Makefile +++ b/tfv/Makefile @@ -52,7 +52,7 @@ TFV_FLYING: tfv_flying.o tfv_flying.o: tfv_flying.s \ gr_hlin.s gr_putsprite.s \ tfv_help.s \ - tfv_sprites.inc + flying_mode7.s flying_sprites.inc ca65 -o tfv_flying.o tfv_flying.s -l tfv_flying.lst ### diff --git a/tfv/flying_mode7.s b/tfv/flying_mode7.s new file mode 100644 index 00000000..5dba52df --- /dev/null +++ b/tfv/flying_mode7.s @@ -0,0 +1,627 @@ +;=========================== +; Draw the Mode7 Background +;=========================== + +draw_background_mode7: + + ; Only draw sky if necessary + ; (at start, or if we have switched to text, we never overwrite it) + + lda DRAW_SKY ; 3 + beq no_draw_sky ;^2nt/3 + ;============== + ; 6 + ; Draw Sky + ; not performance critical as this happens rarely + + dec DRAW_SKY ; usually 2 as we redraw both pages ; 5 + lda #COLOR_BOTH_MEDIUMBLUE ; MEDIUMBLUE color ; 2 + sta COLOR ; 3 + lda #0 ; 2 + ;=========== + ; 11 + +sky_loop: ; draw line across screen + ldy #39 ; from y=0 to y=6 ; 2 + sty V2 ; 3 + ldy #0 ; 2 + pha ; 3 + jsr hlin_double ; hlin y,V2 at A ; 63+(X*16) + pla ; 4 + clc ; 2 + adc #2 ; 2 + cmp #6 ; 2 + bne sky_loop ; 3/2nt + ;============= + ; (23+63+(X*16))*5 + ; Draw Hazy Horizon + + lda #COLOR_BOTH_GREY ; Horizon is Grey ; 2 + sta COLOR ; 3 + lda #6 ; draw single line at 6/7 ; 2 + ldy #39 ; 2 + sty V2 ; hlin Y,V2 at A ; 3 + ldy #0 ; 2 + jsr hlin_double ; hlin 0,40 at 6 ; 63+(X*16) + ;=========== + ; 63+(X*16)+14 + +no_draw_sky: + + ; setup initial odd/even color mask + lda #$f0 ; 2 + sta COLOR_MASK ; 3 + + ; start Y at 8 (below horizon line) + lda #8 ; 2 + sta SCREEN_Y ; 3 + ;============= + ; 10 + +screeny_loop: + and #$fe ; be sure SCREEN_Y used later is even ; 2 + tay ; put in Y for lookup table later ; 2 + + lda COLOR_MASK ; flip mask for odd/even row plotting ; 3 + eor #$ff ; 2 + sta COLOR_MASK ; 3 + sta mask_label+1 ; setup self-modifying code ; 4 + + eor #$ff ; setup self-modifying branch later ; 2 + bmi odd_branch ; beq is $f0 (too clever FIXME) ; 2nt/3 + lda #$d0 ; bne is $d0 ; 2 +odd_branch: + sta mask_branch_label ; actually update branch ; 4 + ;============ + ; 27 + +setup_gr_addr: + lda gr_offsets,Y ; lookup low-res memory row address ; 4 + sta GBASL ; store in GBASL zero-page pointer ; 3 + iny ; point to high part of address ; 2 + + lda gr_offsets,Y ; load high part of address ; 4 + clc ; clear carry for add ; 2 + adc DRAW_PAGE ; add in draw page offset ; 3 + sta GBASH ; store in GBASH zero-page pointer ; 3 + + ;============= + ; 21 + +calc_horizontal_scale: + + ; Calculate the horizontal scale using a lookup table + + ; horizontal_scale.i *ALWAYS* = 0 + + ; unsigned char horizontal_lookup[7][32]; + ;horizontal_scale.f= + ; horizontal_lookup[space_z.i&0xf][(screen_y-8)/2]; + ; horizontal_lookup[(space_z<<5)+(screen_y-8)] + + + clc ; 2 + lda SCREEN_Y ; 3 +spacez_shifted: + adc #0 ; self-modify, loads (spacez<<5)-8 ; 2 + tay ; 2 + lda horizontal_lookup,Y ; 4 + sta NUM1L ; HORIZ_SCALE_F is input to next mul ; 3 + ;============ + ; 16 + +; mul2 + ; calculate the distance of the line we are drawing + ; fixed_mul(&horizontal_scale,&scale,&distance); + lda #0 ; HORIZ_SCALE_I is always zero ; 2 + sta NUM1H ; 3 + ; NUM1L was set to HORIZ_SCALE_F previously ; + lda #CONST_SCALE_I ; SCALE_I ; 2 + sta NUM2H ; 3 + lda #CONST_SCALE_F ; SCALE_F ; 2 + sta NUM2L ; 3 + sec ; don't reuse previous settings ; 2 + jsr multiply ; 6 + stx DISTANCE_I ; 2 + sta DISTANCE_F ; 2 + ;========== + ; 27 + + ; calculate the dx and dy to add to points in space + ; we add to the starting values on each row to get the next + ; space values + + ; dx.i=fixed_sin[(angle+8)&0xf].i // -sin() + lda ANGLE ; 3 + clc ; 2 + adc #8 ; 2 + and #$f ; 2 + asl ; 2 + tay ; 2 + lda fixed_sin,Y ; load integer half ; 4 + sta NUM2H ; use as source in upcomnig mul ; 3 + + + ; dx.f=fixed_sin[(angle+8)&0xf].f; // -sin() + iny ; point to float half ; 2 + lda fixed_sin,Y ; load it from lookup table ; 4 + sta NUM2L ; use as source in upcoming mul ; 3 + ;========== + ; 29 + +;mul3 + ; fixed_mul(&dx,&horizontal_scale,&dx); + + ; DX_I:DX_F already set in NUM2H:NUM2L + clc ; reuse HORIZ_SCALE in NUM1 ; 2 + jsr multiply ; 6 + stx DX_I ; 3 + sta DX_F ; 3 + ;========== + ; 14 + + ; dy.i=fixed_sin[(angle+4)&0xf].i; // cos() + + lda ANGLE ; 3 + clc ; 2 + adc #4 ; 2 + and #$f ; 2 + asl ; 2 + tay ; 2 + lda fixed_sin,Y ; load integer half ; 4 + sta NUM2H ; use as source in upcoming mul ; 3 + + ; dy.f=fixed_sin[(angle+4)&0xf].f; // cos() + + iny ; point to float half ; 2 + lda fixed_sin,Y ; load from lookup table ; 4 + sta NUM2L ; use as source in upcoming mul ; 3 + ;========== + ; 29 +;mul4 + ; fixed_mul(&dy,&horizontal_scale,&dy); + + ; DY_I:DY_F already in NUM2H:NUM2L + clc ; reuse horiz_scale in num1 ; 2 + jsr multiply ; 6 + stx DY_I ; 3 + sta DY_F ; 3 + ;========== + ; 14 + + ;================================= + ; calculate the starting position + ;================================= + + ; fixed_add(&distance,&factor,&space_x); + clc ; fixed_add(&distance,&factor,&space_y); ; 2 + lda DISTANCE_F ; 3 + adc FACTOR_F ; 3 + sta SPACEY_F ; 3 + sta SPACEX_F ; 3 + + lda DISTANCE_I ; 3 + adc FACTOR_I ; 3 + sta SPACEY_I ; 3 + sta SPACEX_I ; 3 + ;========== + ; 26 + + + ; temp.i=fixed_sin[(angle+4)&0xf].i; // cos() + + lda ANGLE ; 3 + clc ; 2 + adc #4 ; 2 + and #$f ; 2 + asl ; 2 + tay ; 2 + lda fixed_sin,Y ; 4 + sta NUM2H ; store as source for next mul ; 3 + + + ; temp.f=fixed_sin[(angle+4)&0xf].f; // cos() + iny ; 2 + lda fixed_sin,Y ; 4 + sta NUM2L ; store as source for next mul ; 3 + ;========== + ; 29 + +; mul5 + ; fixed_mul(&space_x,&temp,&space_x); + lda SPACEX_I ; 3 + sta NUM1H ; 3 + lda SPACEX_F ; 3 + sta NUM1L ; 3 + ; NUM2H:NUM2L already set above + sec ; don't reuse previous NUM1 ; 2 + jsr multiply ; 6 + ; SPACEX_I in X ; + ; SPACEX_F in A ; + ;========== + ; 20 + + ; fixed_add(&space_x,&cx,&space_x); + clc ; 2 + ; SPACEX_F still in A ; + adc CX_F ; 3 + sta SPACEX_F ; 3 + txa ; SPACEX_I was in X ; 2 + adc CX_I ; 3 + sta SPACEX_I ; 3 + ;=========== + ; 16 + + + ; temp.i=fixed_sin[angle&0xf].i; // sin() + lda ANGLE ; 3 + and #$f ; 2 + asl ; 2 + tay ; 2 + lda fixed_sin,Y ; 4 + sta NUM2H ; store for next mul ; 3 + + ; fixed_temp.f=fixed_sin[angle&0xf].f; // sin() + iny ; 2 + lda fixed_sin,Y ; 4 + sta NUM2L ; store for next mul ; 3 + ;========== + ; 25 + +;mul6 + ; fixed_mul(&space_y,&fixed_temp,&space_y); + lda SPACEY_I ; 3 + sta NUM1H ; 3 + lda SPACEY_F ; 3 + sta NUM1L ; 3 + ; NUM2H:NUM2L already set + sec ; don't reuse previous num1 ; 2 + jsr multiply ; 6 + ; SPACEY_I in X ; + ; SPACEY_F in A ; + ;========== + ; 20 + + ; fixed_add(&space_y,&cy,&space_y); + clc ; 2 + ; SPACEY_F in A + adc CY_F ; 3 + sta SPACEY_F ; 3 + txa ; SPACEY_I in X ; 2 + adc CY_I ; 3 + sta SPACEY_I ; 3 + ;========== + ; 16 +; mul7 + ; fixed_mul(&lowres_half,&dx,&temp); + lda #CONST_LOWRES_HALF_I ; 2 + sta NUM1H ; 3 + lda #CONST_LOWRES_HALF_F ; 2 + sta NUM1L ; 3 + lda DX_I ; 3 + sta NUM2H ; 3 + sta dxi_label+1 ; for self modify ; 4 + lda DX_F ; 3 + sta dxf_label+1 ; for self modify ; 4 + sta NUM2L ; 3 + sec ; don't reuse previous num1 ; 2 + jsr multiply ; 6 + ; TEMP_I in X ; + ; TEMP_F in A ; + ;========== + ; 38 + + + ; fixed_add(&space_x,&temp,&space_x); + clc ; 2 + ; TEMP_F in A + adc SPACEX_F ; 3 + sta SPACEX_F ; 3 + txa ; TEMP_I in X ; 2 + adc SPACEX_I ; 3 + sta SPACEX_I ; 3 + ;========== + ; 16 + +;mul8 + ; fixed_mul(&fixed_temp,&dy,&fixed_temp); + lda DY_I ; 3 + sta NUM2H ; 3 + sta dyi_label+1 ; for self modify ; 4 + lda DY_F ; 3 + sta NUM2L ; 3 + sta dyf_label+1 ; for self modify ; 4 + clc ; reuse CONST_LOWRES_HALF from last time ; 2 + jsr multiply ; 6 + ; TEMP_I in X + ; TEMP_F in A + ;========== + ; 28 + + ; fixed_add(&space_y,&temp,&space_y); + clc ; 2 + ; TEMP_F in A + adc SPACEY_F ; 3 + sta SPACEY_F ; 3 + + txa ; TEMP_I in X ; 2 + adc SPACEY_I ; 3 + sta SPACEY_I ; 3 + + ;========== + ; 16 + + + ldx #40 ; was SCREEN_X ; 2 + ;========== + ; 2 + ;=================================================== + ; SCREEN_X LOOP!!!! + ; every cycle in here counts for 32*40=1280 cycles + ;=================================================== +screenx_loop: + + +nomatch: + ;==================================== + ; do a full lookup, takes much longer + ; used to be a separate function but we inlined it here + + ;==================== + ; lookup_map + ;==================== + ; finds value in space_x.i,space_y.i + ; returns color in A + ; CLOBBERS: A,Y + + lda SPACEX_I ; 3 + sta spacex_label+1 ; self modifying code, LAST_SPACEX_I ; 4 + and #CONST_MAP_MASK_X ; wrap at 64 ; 2 + sta SPACEX_I ; store i patch out ; 3 + tay ; copy to Y for later ; 2 + + lda SPACEY_I ; 3 + sta spacey_label+1 ; self modifying code, LAST_SPACEY_I ; 4 + and #CONST_MAP_MASK_Y ; wrap to 64x64 grid ; 2 + sta SPACEY_I ; 3 + + asl ; 2 + asl ; 2 + asl ; multiply by 8 ; 2 + clc ; 2 + adc SPACEX_I ; add in X value ; 3 + ; only valid if x<8 and y<8 + + ; SPACEX_I is also in y + cpy #$8 ; 2 + ;============ + ; 39 + + bcs ocean_color ; bgt 8 ; 2nt/3 + ldy SPACEY_I ; 3 + cpy #$8 ; 2 + ;============= + ; 7 + + bcs ocean_color ; bgt 8 ; 2nt/3 + + tay ; 2 + lda flying_map,Y ; load from array ; 4 + + bcc update_cache ; 3 + ;============ + ; 11 +ocean_color: + and #$1f ; 2 + tay ; 2 + lda water_map,Y ; the color of the sea ; 4 + ;=========== + ; 8 + +update_cache: + sta map_color_label+1 ; self-modifying ; 4 + + ;=========== + ; 4 + +; rts ; 6 + + + +; jsr lookup_map ; get color in A ; 6 +; ;============ + ; 6 +match: + +mask_label: + and #0 ; COLOR_MASK (self modifying) ; 2 + + ldy #0 ; 2 +mask_branch_label: + beq big_bottom ; this branch is modified based on odd/even + ; F0=beq, D0=bne ; 2nt/3 + + ora (GBASL),Y ; we're odd, or the bottom in ; 5 +big_bottom: + + sta (GBASL),Y ; plot double height pixel ; 6 + inc GBASL ; point to next pixel ; 5 + ;============ + ; 22/18 + + + + ; advance to the next position in space + + ; fixed_add(&space_x,&dx,&space_x); + + clc ; 2 + lda SPACEX_F ; 3 +dxf_label: + adc #0 ; self modifying, is DX_F ; 2 + sta SPACEX_F ; 3 + lda SPACEX_I ; 3 +dxi_label: + adc #0 ; self modifying, is DX_I ; 2 + sta SPACEX_I ; 3 + ;========== + ; 18 + + ; fixed_add(&space_y,&dy,&space_y); + + clc ; 2 + lda SPACEY_F ; 3 +dyf_label: + adc #0 ; self modifyig, is DY_F ; 2 + sta SPACEY_F ; 3 + lda SPACEY_I ; 3 +dyi_label: + adc #0 ; self mofidying is DY_I ; 2 + sta SPACEY_I ; 3 + ;============ + ; 18 + + dex ; decrement SCREEN_X ; 2 + beq done_screenx_loop ; branch until we've done 40 ; 2nt/3 + ;============= + ; 4/5 + + + ; cache color and return if same as last time + lda SPACEY_I ; 3 +spacey_label: + cmp #0 ; self modify, LAST_SPACEY_I ; 2 + bne nomatch ; 2nt/3 + lda SPACEX_I ; 3 +spacex_label: + cmp #0 ; self modify, LAST_SPACEX_I ; 2 + bne nomatch ; 2nt/3 +map_color_label: + lda #0 ; self modify, LAST_MAP_COLOR ; 2 + jmp match ; 3 + +done_screenx_loop: + inc SCREEN_Y ; 5 + lda SCREEN_Y ; 3 + cmp #40 ; LOWRES height ; 2 + beq done_screeny ; 2nt/3 + jmp screeny_loop ; too far to branch ; 3 + ;============= + ; 15 +done_screeny: + rts ; 6 + + + ;==================== + ; lookup_map + ;==================== + ; finds value in space_x.i,space_y.i + ; returns color in A + ; CLOBBERS: A,Y + ; this is used to check if above water or grass + ; the high-performance per-pixel version has been inlined +lookup_map: + lda SPACEX_I ; 3 + and #CONST_MAP_MASK_X ; 2 + sta SPACEX_I ; 3 + tay ; 2 + + lda SPACEY_I ; 3 + and #CONST_MAP_MASK_Y ; wrap to 64x64 grid ; 2 + sta SPACEY_I ; 3 + + asl ; 2 + asl ; 2 + asl ; multiply by 8 ; 2 + clc ; 2 + adc SPACEX_I ; add in X value ; 3 + ; only valid if x<8 and y<8 + + ; SPACEX_I is in y + cpy #$8 ; 2 + ;============ + ; 31 + + bcs ocean_color_outline ; bgt 8 ;^2nt/3 + ldy SPACEY_I ; 3 + cpy #$8 ; 2 + bcs ocean_color_outline ; bgt 8 ; 2nt/3 + + tay ; 2 + lda flying_map,Y ; load from array ; 4 + + bcc update_cache_outline ; 3 + +ocean_color_outline: + and #$1f ; 2 + tay ; 2 + lda water_map,Y ; the color of the sea ; 4 + +update_cache_outline: + rts ; 6 + +; 8.8 fixed point +; should we store as two arrays, one I one F? +fixed_sin: + .byte $00,$00 ; 0.000000=00.00 + .byte $00,$61 ; 0.382683=00.61 + .byte $00,$b5 ; 0.707107=00.b5 + .byte $00,$ec ; 0.923880=00.ec + .byte $01,$00 ; 1.000000=01.00 + .byte $00,$ec ; 0.923880=00.ec + .byte $00,$b5 ; 0.707107=00.b5 + .byte $00,$61 ; 0.382683=00.61 + .byte $00,$00 ; 0.000000=00.00 + .byte $ff,$9f ; -0.382683=ff.9f + .byte $ff,$4b ; -0.707107=ff.4b + .byte $ff,$14 ; -0.923880=ff.14 + .byte $ff,$00 ; -1.000000=ff.00 + .byte $ff,$14 ; -0.923880=ff.14 + .byte $ff,$4b ; -0.707107=ff.4b + .byte $ff,$9f ; -0.382683=ff.9f + +fixed_sin_scale: + .byte $00,$00 + .byte $00,$0c + .byte $00,$16 + .byte $00,$1d + .byte $00,$20 + .byte $00,$1d + .byte $00,$16 + .byte $00,$0c + .byte $00,$00 + .byte $ff,$f4 + .byte $ff,$ea + .byte $ff,$e3 + .byte $ff,$e0 + .byte $ff,$e3 + .byte $ff,$ea + .byte $ff,$f4 + +;horizontal_lookup_20: +; .byte $0C,$0A,$09,$08,$07,$06,$05,$05,$04,$04,$04,$04,$03,$03,$03,$03 +; .byte $26,$20,$1B,$18,$15,$13,$11,$10,$0E,$0D,$0C,$0C,$0B,$0A,$0A,$09 +; .byte $40,$35,$2D,$28,$23,$20,$1D,$1A,$18,$16,$15,$14,$12,$11,$10,$10 +; .byte $59,$4A,$40,$38,$31,$2C,$28,$25,$22,$20,$1D,$1C,$1A,$18,$17,$16 +; .byte $73,$60,$52,$48,$40,$39,$34,$30,$2C,$29,$26,$24,$21,$20,$1E,$1C +; .byte $8C,$75,$64,$58,$4E,$46,$40,$3A,$36,$32,$2E,$2C,$29,$27,$25,$23 +; .byte $A6,$8A,$76,$68,$5C,$53,$4B,$45,$40,$3B,$37,$34,$30,$2E,$2B,$29 + + ; we can guarantee 4 cycle indexed reads if we page-aligned this +;.align 256 +horizontal_lookup: + .byte $0C,$0B,$0A,$09,$09,$08,$08,$07,$07,$06,$06,$06,$05,$05,$05,$05 + .byte $04,$04,$04,$04,$04,$04,$04,$03,$03,$03,$03,$03,$03,$03,$03,$03 + .byte $26,$22,$20,$1D,$1B,$19,$18,$16,$15,$14,$13,$12,$11,$10,$10,$0F + .byte $0E,$0E,$0D,$0D,$0C,$0C,$0C,$0B,$0B,$0A,$0A,$0A,$0A,$09,$09,$09 + .byte $40,$3A,$35,$31,$2D,$2A,$28,$25,$23,$21,$20,$1E,$1D,$1B,$1A,$19 + .byte $18,$17,$16,$16,$15,$14,$14,$13,$12,$12,$11,$11,$10,$10,$10,$0F + .byte $59,$51,$4A,$44,$40,$3B,$38,$34,$31,$2F,$2C,$2A,$28,$26,$25,$23 + .byte $22,$21,$20,$1E,$1D,$1C,$1C,$1B,$1A,$19,$18,$18,$17,$16,$16,$15 + .byte $73,$68,$60,$58,$52,$4C,$48,$43,$40,$3C,$39,$36,$34,$32,$30,$2E + .byte $2C,$2A,$29,$27,$26,$25,$24,$22,$21,$20,$20,$1F,$1E,$1D,$1C,$1C + .byte $8C,$80,$75,$6C,$64,$5D,$58,$52,$4E,$4A,$46,$43,$40,$3D,$3A,$38 + .byte $36,$34,$32,$30,$2E,$2D,$2C,$2A,$29,$28,$27,$26,$25,$24,$23,$22 + .byte $A6,$97,$8A,$80,$76,$6E,$68,$61,$5C,$57,$53,$4F,$4B,$48,$45,$42 + .byte $40,$3D,$3B,$39,$37,$35,$34,$32,$30,$2F,$2E,$2C,$2B,$2A,$29,$28 + diff --git a/tfv/flying_sprites.inc b/tfv/flying_sprites.inc new file mode 100644 index 00000000..3c68fe72 --- /dev/null +++ b/tfv/flying_sprites.inc @@ -0,0 +1,58 @@ +;================ +; Ship Sprites +;================ + +splash_forward: + .byte $7,$2 + .byte $00,$ee,$00,$00,$00,$ee,$00 + .byte $ee,$00,$00,$00,$00,$00,$ee + +splash_right: + .byte $7,$2 + .byte $00,$00,$00,$00,$00,$ee,$00 + .byte $00,$00,$00,$00,$00,$00,$ee + + +splash_left: + .byte $7,$2 + .byte $00,$ee,$00,$00,$00,$00,$00 + .byte $ee,$00,$00,$00,$00,$00,$00 + +shadow_forward: + .byte $3,$2 + .byte $00,$aa,$00 + .byte $a0,$aa,$a0 + +shadow_right: + .byte $3,$2 + .byte $a0,$00,$aa + .byte $00,$0a,$a0 + +shadow_left: + .byte $3,$2 + .byte $aa,$00,$a0 + .byte $a0,$0a,$00 + +ship_forward: + .byte $9,$5 + .byte $00,$00,$00,$00,$ff,$00,$00,$00,$00 + .byte $00,$00,$00,$66,$ff,$66,$00,$00,$00 + .byte $00,$00,$70,$2f,$12,$2f,$70,$00,$00 + .byte $f0,$f7,$f7,$f2,$d9,$f2,$f7,$f7,$f0 + .byte $00,$00,$00,$00,$0d,$00,$00,$00,$00 + +ship_right: + .byte $9,$5 + .byte $00,$00,$00,$00,$00,$60,$60,$f0,$00 + .byte $00,$f0,$70,$70,$f6,$f6,$6f,$66,$00 + .byte $00,$07,$ff,$2f,$12,$27,$f6,$00,$00 + .byte $00,$00,$00,$dd,$d9,$f2,$77,$00,$00 + .byte $00,$00,$00,$00,$00,$0f,$ff,$70,$00 + +ship_left: + .byte $9,$5 + .byte $00,$f0,$60,$60,$00,$00,$00,$00,$00 + .byte $00,$66,$6f,$f6,$f6,$70,$70,$f0,$00 + .byte $00,$00,$f6,$27,$12,$2f,$ff,$07,$00 + .byte $00,$00,$77,$f2,$d9,$dd,$00,$00,$00 + .byte $00,$70,$ff,$0f,$00,$00,$00,$00,$00 diff --git a/tfv/tfv_flying.s b/tfv/tfv_flying.s index d2ed71bf..e3feca0f 100644 --- a/tfv/tfv_flying.s +++ b/tfv/tfv_flying.s @@ -618,567 +618,7 @@ update_z_factor: ; 60 -;=========================== -; Draw the Mode7 Background -;=========================== -draw_background_mode7: - - ; Only draw sky if necessary - ; (at start, or if we have switched to text, we never overwrite it) - - lda DRAW_SKY ; 3 - beq no_draw_sky ;^2nt/3 - ;============== - ; 6 - ; Draw Sky - ; not performance critical as this happens rarely - - dec DRAW_SKY ; usually 2 as we redraw both pages ; 5 - lda #COLOR_BOTH_MEDIUMBLUE ; MEDIUMBLUE color ; 2 - sta COLOR ; 3 - lda #0 ; 2 - ;=========== - ; 11 - -sky_loop: ; draw line across screen - ldy #39 ; from y=0 to y=6 ; 2 - sty V2 ; 3 - ldy #0 ; 2 - pha ; 3 - jsr hlin_double ; hlin y,V2 at A ; 63+(X*16) - pla ; 4 - clc ; 2 - adc #2 ; 2 - cmp #6 ; 2 - bne sky_loop ; 3/2nt - ;============= - ; (23+63+(X*16))*5 - ; Draw Hazy Horizon - - lda #COLOR_BOTH_GREY ; Horizon is Grey ; 2 - sta COLOR ; 3 - lda #6 ; draw single line at 6/7 ; 2 - ldy #39 ; 2 - sty V2 ; hlin Y,V2 at A ; 3 - ldy #0 ; 2 - jsr hlin_double ; hlin 0,40 at 6 ; 63+(X*16) - ;=========== - ; 63+(X*16)+14 - -no_draw_sky: - - ; setup initial odd/even color mask - lda #$f0 ; 2 - sta COLOR_MASK ; 3 - - ; start Y at 8 (below horizon line) - lda #8 ; 2 - sta SCREEN_Y ; 3 - ;============= - ; 10 - -screeny_loop: - and #$fe ; be sure SCREEN_Y used later is even ; 2 - tay ; put in Y for lookup table later ; 2 - - lda COLOR_MASK ; flip mask for odd/even row plotting ; 3 - eor #$ff ; 2 - sta COLOR_MASK ; 3 - sta mask_label+1 ; setup self-modifying code ; 4 - - eor #$ff ; setup self-modifying branch later ; 2 - bmi odd_branch ; beq is $f0 (too clever FIXME) ; 2nt/3 - lda #$d0 ; bne is $d0 ; 2 -odd_branch: - sta mask_branch_label ; actually update branch ; 4 - ;============ - ; 27 - -setup_gr_addr: - lda gr_offsets,Y ; lookup low-res memory row address ; 4 - sta GBASL ; store in GBASL zero-page pointer ; 3 - iny ; point to high part of address ; 2 - - lda gr_offsets,Y ; load high part of address ; 4 - clc ; clear carry for add ; 2 - adc DRAW_PAGE ; add in draw page offset ; 3 - sta GBASH ; store in GBASH zero-page pointer ; 3 - - ;============= - ; 21 - -calc_horizontal_scale: - - ; Calculate the horizontal scale using a lookup table - - ; horizontal_scale.i *ALWAYS* = 0 - - ; unsigned char horizontal_lookup[7][32]; - ;horizontal_scale.f= - ; horizontal_lookup[space_z.i&0xf][(screen_y-8)/2]; - ; horizontal_lookup[(space_z<<5)+(screen_y-8)] - - - clc ; 2 - lda SCREEN_Y ; 3 -spacez_shifted: - adc #0 ; self-modify, loads (spacez<<5)-8 ; 2 - tay ; 2 - lda horizontal_lookup,Y ; 4 - sta NUM1L ; HORIZ_SCALE_F is input to next mul ; 3 - ;============ - ; 16 - -; mul2 - ; calculate the distance of the line we are drawing - ; fixed_mul(&horizontal_scale,&scale,&distance); - lda #0 ; HORIZ_SCALE_I is always zero ; 2 - sta NUM1H ; 3 - ; NUM1L was set to HORIZ_SCALE_F previously ; - lda #CONST_SCALE_I ; SCALE_I ; 2 - sta NUM2H ; 3 - lda #CONST_SCALE_F ; SCALE_F ; 2 - sta NUM2L ; 3 - sec ; don't reuse previous settings ; 2 - jsr multiply ; 6 - stx DISTANCE_I ; 2 - sta DISTANCE_F ; 2 - ;========== - ; 27 - - ; calculate the dx and dy to add to points in space - ; we add to the starting values on each row to get the next - ; space values - - ; dx.i=fixed_sin[(angle+8)&0xf].i // -sin() - lda ANGLE ; 3 - clc ; 2 - adc #8 ; 2 - and #$f ; 2 - asl ; 2 - tay ; 2 - lda fixed_sin,Y ; load integer half ; 4 - sta NUM2H ; use as source in upcomnig mul ; 3 - - - ; dx.f=fixed_sin[(angle+8)&0xf].f; // -sin() - iny ; point to float half ; 2 - lda fixed_sin,Y ; load it from lookup table ; 4 - sta NUM2L ; use as source in upcoming mul ; 3 - ;========== - ; 29 - -;mul3 - ; fixed_mul(&dx,&horizontal_scale,&dx); - - ; DX_I:DX_F already set in NUM2H:NUM2L - clc ; reuse HORIZ_SCALE in NUM1 ; 2 - jsr multiply ; 6 - stx DX_I ; 3 - sta DX_F ; 3 - ;========== - ; 14 - - ; dy.i=fixed_sin[(angle+4)&0xf].i; // cos() - - lda ANGLE ; 3 - clc ; 2 - adc #4 ; 2 - and #$f ; 2 - asl ; 2 - tay ; 2 - lda fixed_sin,Y ; load integer half ; 4 - sta NUM2H ; use as source in upcoming mul ; 3 - - ; dy.f=fixed_sin[(angle+4)&0xf].f; // cos() - - iny ; point to float half ; 2 - lda fixed_sin,Y ; load from lookup table ; 4 - sta NUM2L ; use as source in upcoming mul ; 3 - ;========== - ; 29 -;mul4 - ; fixed_mul(&dy,&horizontal_scale,&dy); - - ; DY_I:DY_F already in NUM2H:NUM2L - clc ; reuse horiz_scale in num1 ; 2 - jsr multiply ; 6 - stx DY_I ; 3 - sta DY_F ; 3 - ;========== - ; 14 - - ;================================= - ; calculate the starting position - ;================================= - - ; fixed_add(&distance,&factor,&space_x); - clc ; fixed_add(&distance,&factor,&space_y); ; 2 - lda DISTANCE_F ; 3 - adc FACTOR_F ; 3 - sta SPACEY_F ; 3 - sta SPACEX_F ; 3 - - lda DISTANCE_I ; 3 - adc FACTOR_I ; 3 - sta SPACEY_I ; 3 - sta SPACEX_I ; 3 - ;========== - ; 26 - - - ; temp.i=fixed_sin[(angle+4)&0xf].i; // cos() - - lda ANGLE ; 3 - clc ; 2 - adc #4 ; 2 - and #$f ; 2 - asl ; 2 - tay ; 2 - lda fixed_sin,Y ; 4 - sta NUM2H ; store as source for next mul ; 3 - - - ; temp.f=fixed_sin[(angle+4)&0xf].f; // cos() - iny ; 2 - lda fixed_sin,Y ; 4 - sta NUM2L ; store as source for next mul ; 3 - ;========== - ; 29 - -; mul5 - ; fixed_mul(&space_x,&temp,&space_x); - lda SPACEX_I ; 3 - sta NUM1H ; 3 - lda SPACEX_F ; 3 - sta NUM1L ; 3 - ; NUM2H:NUM2L already set above - sec ; don't reuse previous NUM1 ; 2 - jsr multiply ; 6 - ; SPACEX_I in X ; - ; SPACEX_F in A ; - ;========== - ; 20 - - ; fixed_add(&space_x,&cx,&space_x); - clc ; 2 - ; SPACEX_F still in A ; - adc CX_F ; 3 - sta SPACEX_F ; 3 - txa ; SPACEX_I was in X ; 2 - adc CX_I ; 3 - sta SPACEX_I ; 3 - ;=========== - ; 16 - - - ; temp.i=fixed_sin[angle&0xf].i; // sin() - lda ANGLE ; 3 - and #$f ; 2 - asl ; 2 - tay ; 2 - lda fixed_sin,Y ; 4 - sta NUM2H ; store for next mul ; 3 - - ; fixed_temp.f=fixed_sin[angle&0xf].f; // sin() - iny ; 2 - lda fixed_sin,Y ; 4 - sta NUM2L ; store for next mul ; 3 - ;========== - ; 25 - -;mul6 - ; fixed_mul(&space_y,&fixed_temp,&space_y); - lda SPACEY_I ; 3 - sta NUM1H ; 3 - lda SPACEY_F ; 3 - sta NUM1L ; 3 - ; NUM2H:NUM2L already set - sec ; don't reuse previous num1 ; 2 - jsr multiply ; 6 - ; SPACEY_I in X ; - ; SPACEY_F in A ; - ;========== - ; 20 - - ; fixed_add(&space_y,&cy,&space_y); - clc ; 2 - ; SPACEY_F in A - adc CY_F ; 3 - sta SPACEY_F ; 3 - txa ; SPACEY_I in X ; 2 - adc CY_I ; 3 - sta SPACEY_I ; 3 - ;========== - ; 16 -; mul7 - ; fixed_mul(&lowres_half,&dx,&temp); - lda #CONST_LOWRES_HALF_I ; 2 - sta NUM1H ; 3 - lda #CONST_LOWRES_HALF_F ; 2 - sta NUM1L ; 3 - lda DX_I ; 3 - sta NUM2H ; 3 - sta dxi_label+1 ; for self modify ; 4 - lda DX_F ; 3 - sta dxf_label+1 ; for self modify ; 4 - sta NUM2L ; 3 - sec ; don't reuse previous num1 ; 2 - jsr multiply ; 6 - ; TEMP_I in X ; - ; TEMP_F in A ; - ;========== - ; 38 - - - ; fixed_add(&space_x,&temp,&space_x); - clc ; 2 - ; TEMP_F in A - adc SPACEX_F ; 3 - sta SPACEX_F ; 3 - txa ; TEMP_I in X ; 2 - adc SPACEX_I ; 3 - sta SPACEX_I ; 3 - ;========== - ; 16 - -;mul8 - ; fixed_mul(&fixed_temp,&dy,&fixed_temp); - lda DY_I ; 3 - sta NUM2H ; 3 - sta dyi_label+1 ; for self modify ; 4 - lda DY_F ; 3 - sta NUM2L ; 3 - sta dyf_label+1 ; for self modify ; 4 - clc ; reuse CONST_LOWRES_HALF from last time ; 2 - jsr multiply ; 6 - ; TEMP_I in X - ; TEMP_F in A - ;========== - ; 28 - - ; fixed_add(&space_y,&temp,&space_y); - clc ; 2 - ; TEMP_F in A - adc SPACEY_F ; 3 - sta SPACEY_F ; 3 - - txa ; TEMP_I in X ; 2 - adc SPACEY_I ; 3 - sta SPACEY_I ; 3 - - ;========== - ; 16 - - - ldx #40 ; was SCREEN_X ; 2 - ;========== - ; 2 - ;=================================================== - ; SCREEN_X LOOP!!!! - ; every cycle in here counts for 32*40=1280 cycles - ;=================================================== -screenx_loop: - - -nomatch: - ;==================================== - ; do a full lookup, takes much longer - ; used to be a separate function but we inlined it here - - ;==================== - ; lookup_map - ;==================== - ; finds value in space_x.i,space_y.i - ; returns color in A - ; CLOBBERS: A,Y - - lda SPACEX_I ; 3 - sta spacex_label+1 ; self modifying code, LAST_SPACEX_I ; 4 - and #CONST_MAP_MASK_X ; wrap at 64 ; 2 - sta SPACEX_I ; store i patch out ; 3 - tay ; copy to Y for later ; 2 - - lda SPACEY_I ; 3 - sta spacey_label+1 ; self modifying code, LAST_SPACEY_I ; 4 - and #CONST_MAP_MASK_Y ; wrap to 64x64 grid ; 2 - sta SPACEY_I ; 3 - - asl ; 2 - asl ; 2 - asl ; multiply by 8 ; 2 - clc ; 2 - adc SPACEX_I ; add in X value ; 3 - ; only valid if x<8 and y<8 - - ; SPACEX_I is also in y - cpy #$8 ; 2 - ;============ - ; 39 - - bcs ocean_color ; bgt 8 ; 2nt/3 - ldy SPACEY_I ; 3 - cpy #$8 ; 2 - ;============= - ; 7 - - bcs ocean_color ; bgt 8 ; 2nt/3 - - tay ; 2 - lda flying_map,Y ; load from array ; 4 - - bcc update_cache ; 3 - ;============ - ; 11 -ocean_color: - and #$1f ; 2 - tay ; 2 - lda water_map,Y ; the color of the sea ; 4 - ;=========== - ; 8 - -update_cache: - sta map_color_label+1 ; self-modifying ; 4 - - ;=========== - ; 4 - -; rts ; 6 - - - -; jsr lookup_map ; get color in A ; 6 -; ;============ - ; 6 -match: - -mask_label: - and #0 ; COLOR_MASK (self modifying) ; 2 - - ldy #0 ; 2 -mask_branch_label: - beq big_bottom ; this branch is modified based on odd/even - ; F0=beq, D0=bne ; 2nt/3 - - ora (GBASL),Y ; we're odd, or the bottom in ; 5 -big_bottom: - - sta (GBASL),Y ; plot double height pixel ; 6 - inc GBASL ; point to next pixel ; 5 - ;============ - ; 22/18 - - - - ; advance to the next position in space - - ; fixed_add(&space_x,&dx,&space_x); - - clc ; 2 - lda SPACEX_F ; 3 -dxf_label: - adc #0 ; self modifying, is DX_F ; 2 - sta SPACEX_F ; 3 - lda SPACEX_I ; 3 -dxi_label: - adc #0 ; self modifying, is DX_I ; 2 - sta SPACEX_I ; 3 - ;========== - ; 18 - - ; fixed_add(&space_y,&dy,&space_y); - - clc ; 2 - lda SPACEY_F ; 3 -dyf_label: - adc #0 ; self modifyig, is DY_F ; 2 - sta SPACEY_F ; 3 - lda SPACEY_I ; 3 -dyi_label: - adc #0 ; self mofidying is DY_I ; 2 - sta SPACEY_I ; 3 - ;============ - ; 18 - - dex ; decrement SCREEN_X ; 2 - beq done_screenx_loop ; branch until we've done 40 ; 2nt/3 - ;============= - ; 4/5 - - - ; cache color and return if same as last time - lda SPACEY_I ; 3 -spacey_label: - cmp #0 ; self modify, LAST_SPACEY_I ; 2 - bne nomatch ; 2nt/3 - lda SPACEX_I ; 3 -spacex_label: - cmp #0 ; self modify, LAST_SPACEX_I ; 2 - bne nomatch ; 2nt/3 -map_color_label: - lda #0 ; self modify, LAST_MAP_COLOR ; 2 - jmp match ; 3 - -done_screenx_loop: - inc SCREEN_Y ; 5 - lda SCREEN_Y ; 3 - cmp #40 ; LOWRES height ; 2 - beq done_screeny ; 2nt/3 - jmp screeny_loop ; too far to branch ; 3 - ;============= - ; 15 -done_screeny: - rts ; 6 - - - ;==================== - ; lookup_map - ;==================== - ; finds value in space_x.i,space_y.i - ; returns color in A - ; CLOBBERS: A,Y - ; this is used to check if above water or grass - ; the high-performance per-pixel version has been inlined -lookup_map: - lda SPACEX_I ; 3 - and #CONST_MAP_MASK_X ; 2 - sta SPACEX_I ; 3 - tay ; 2 - - lda SPACEY_I ; 3 - and #CONST_MAP_MASK_Y ; wrap to 64x64 grid ; 2 - sta SPACEY_I ; 3 - - asl ; 2 - asl ; 2 - asl ; multiply by 8 ; 2 - clc ; 2 - adc SPACEX_I ; add in X value ; 3 - ; only valid if x<8 and y<8 - - ; SPACEX_I is in y - cpy #$8 ; 2 - ;============ - ; 31 - - bcs ocean_color_outline ; bgt 8 ;^2nt/3 - ldy SPACEY_I ; 3 - cpy #$8 ; 2 - bcs ocean_color_outline ; bgt 8 ; 2nt/3 - - tay ; 2 - lda flying_map,Y ; load from array ; 4 - - bcc update_cache_outline ; 3 - -ocean_color_outline: - and #$1f ; 2 - tay ; 2 - lda water_map,Y ; the color of the sea ; 4 - -update_cache_outline: - rts ; 6 flying_map: @@ -1198,73 +638,8 @@ water_map: .byte $22,$22,$22,$22, $22,$22,$22,$22 .byte $22,$22,$22,$22, $ee,$22,$22,$22 -.include "multiply_fast.s" -; 8.8 fixed point -; should we store as two arrays, one I one F? -fixed_sin: - .byte $00,$00 ; 0.000000=00.00 - .byte $00,$61 ; 0.382683=00.61 - .byte $00,$b5 ; 0.707107=00.b5 - .byte $00,$ec ; 0.923880=00.ec - .byte $01,$00 ; 1.000000=01.00 - .byte $00,$ec ; 0.923880=00.ec - .byte $00,$b5 ; 0.707107=00.b5 - .byte $00,$61 ; 0.382683=00.61 - .byte $00,$00 ; 0.000000=00.00 - .byte $ff,$9f ; -0.382683=ff.9f - .byte $ff,$4b ; -0.707107=ff.4b - .byte $ff,$14 ; -0.923880=ff.14 - .byte $ff,$00 ; -1.000000=ff.00 - .byte $ff,$14 ; -0.923880=ff.14 - .byte $ff,$4b ; -0.707107=ff.4b - .byte $ff,$9f ; -0.382683=ff.9f - -fixed_sin_scale: - .byte $00,$00 - .byte $00,$0c - .byte $00,$16 - .byte $00,$1d - .byte $00,$20 - .byte $00,$1d - .byte $00,$16 - .byte $00,$0c - .byte $00,$00 - .byte $ff,$f4 - .byte $ff,$ea - .byte $ff,$e3 - .byte $ff,$e0 - .byte $ff,$e3 - .byte $ff,$ea - .byte $ff,$f4 - -;horizontal_lookup_20: -; .byte $0C,$0A,$09,$08,$07,$06,$05,$05,$04,$04,$04,$04,$03,$03,$03,$03 -; .byte $26,$20,$1B,$18,$15,$13,$11,$10,$0E,$0D,$0C,$0C,$0B,$0A,$0A,$09 -; .byte $40,$35,$2D,$28,$23,$20,$1D,$1A,$18,$16,$15,$14,$12,$11,$10,$10 -; .byte $59,$4A,$40,$38,$31,$2C,$28,$25,$22,$20,$1D,$1C,$1A,$18,$17,$16 -; .byte $73,$60,$52,$48,$40,$39,$34,$30,$2C,$29,$26,$24,$21,$20,$1E,$1C -; .byte $8C,$75,$64,$58,$4E,$46,$40,$3A,$36,$32,$2E,$2C,$29,$27,$25,$23 -; .byte $A6,$8A,$76,$68,$5C,$53,$4B,$45,$40,$3B,$37,$34,$30,$2E,$2B,$29 - - ; we can guarantee 4 cycle indexed reads if we page-aligned this -;.align 256 -horizontal_lookup: - .byte $0C,$0B,$0A,$09,$09,$08,$08,$07,$07,$06,$06,$06,$05,$05,$05,$05 - .byte $04,$04,$04,$04,$04,$04,$04,$03,$03,$03,$03,$03,$03,$03,$03,$03 - .byte $26,$22,$20,$1D,$1B,$19,$18,$16,$15,$14,$13,$12,$11,$10,$10,$0F - .byte $0E,$0E,$0D,$0D,$0C,$0C,$0C,$0B,$0B,$0A,$0A,$0A,$0A,$09,$09,$09 - .byte $40,$3A,$35,$31,$2D,$2A,$28,$25,$23,$21,$20,$1E,$1D,$1B,$1A,$19 - .byte $18,$17,$16,$16,$15,$14,$14,$13,$12,$12,$11,$11,$10,$10,$10,$0F - .byte $59,$51,$4A,$44,$40,$3B,$38,$34,$31,$2F,$2C,$2A,$28,$26,$25,$23 - .byte $22,$21,$20,$1E,$1D,$1C,$1C,$1B,$1A,$19,$18,$18,$17,$16,$16,$15 - .byte $73,$68,$60,$58,$52,$4C,$48,$43,$40,$3C,$39,$36,$34,$32,$30,$2E - .byte $2C,$2A,$29,$27,$26,$25,$24,$22,$21,$20,$20,$1F,$1E,$1D,$1C,$1C - .byte $8C,$80,$75,$6C,$64,$5D,$58,$52,$4E,$4A,$46,$43,$40,$3D,$3A,$38 - .byte $36,$34,$32,$30,$2E,$2D,$2C,$2A,$29,$28,$27,$26,$25,$24,$23,$22 - .byte $A6,$97,$8A,$80,$76,$6E,$68,$61,$5C,$57,$53,$4F,$4B,$48,$45,$42 - .byte $40,$3D,$3B,$39,$37,$35,$34,$32,$30,$2F,$2E,$2C,$2B,$2A,$29,$28 @@ -1290,5 +665,6 @@ grass_string: .include "tfv_help.s" - -.include "tfv_sprites.inc" +.include "flying_mode7.s" +.include "flying_sprites.inc" +.include "multiply_fast.s"