From bdf64d1d2d7fa61c76c8d269341b78b8d0e509d8 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Sat, 12 Jun 2021 11:37:42 -0400 Subject: [PATCH] starbot: so close --- graphics/gr/starfield/Makefile | 21 +- graphics/gr/starfield/starbot.s | 276 ++++++++++++++----------- graphics/gr/starfield/starbot_lookup.s | 235 +++++++++++++++++++++ 3 files changed, 413 insertions(+), 119 deletions(-) create mode 100644 graphics/gr/starfield/starbot_lookup.s diff --git a/graphics/gr/starfield/Makefile b/graphics/gr/starfield/Makefile index 0a25a07f..8d5214ae 100644 --- a/graphics/gr/starfield/Makefile +++ b/graphics/gr/starfield/Makefile @@ -12,13 +12,16 @@ all: starfield.dsk $(DOS33): cd ../../../utils/dos33fs-utils && make -starfield.dsk: $(DOS33) HELLO STARFIELD_DEMO STARFIELD_1K STARFIELD.BAS STARSMALL +starfield.dsk: $(DOS33) HELLO STARFIELD_DEMO STARFIELD_1K STARFIELD.BAS \ + STARSMALL STARBOT STARBOT_LOOKUP cp $(EMPTY_DISK)/empty.dsk starfield.dsk $(DOS33) -y starfield.dsk SAVE A HELLO $(DOS33) -y starfield.dsk SAVE A STARFIELD.BAS $(DOS33) -y starfield.dsk BSAVE -a 0x1000 STARFIELD_DEMO $(DOS33) -y starfield.dsk BSAVE -a 0x1000 STARFIELD_1K $(DOS33) -y starfield.dsk BSAVE -a 0xc00 STARSMALL + $(DOS33) -y starfield.dsk BSAVE -a 0xc00 STARBOT_LOOKUP + $(DOS33) -y starfield.dsk BSAVE -a 0xc00 STARBOT ### @@ -63,6 +66,22 @@ STARSMALL: starsmall.o starsmall.o: starsmall.s ca65 -o starsmall.o starsmall.s -l starsmall.lst +### + +STARBOT: starbot.o + ld65 -o STARBOT starbot.o -C $(LINKERSCRIPTS)/apple2_c00.inc + +starbot.o: starbot.s + ca65 -o starbot.o starbot.s -l starbot.lst + +### + +STARBOT_LOOKUP: starbot_lookup.o + ld65 -o STARBOT_LOOKUP starbot_lookup.o -C $(LINKERSCRIPTS)/apple2_c00.inc + +starbot_lookup.o: starbot_lookup.s + ca65 -o starbot_lookup.o starbot_lookup.s -l starbot_lookup.lst + ### diff --git a/graphics/gr/starfield/starbot.s b/graphics/gr/starfield/starbot.s index fb73ff9e..5b85ec95 100644 --- a/graphics/gr/starfield/starbot.s +++ b/graphics/gr/starfield/starbot.s @@ -11,9 +11,14 @@ ; 170 bytes - can do sty zp,x ; 163 bytes - lose the cool HGR intro ; 161 bytes - re-arrange RNG location +; 158 bytes - ra-arrange a lot to remove need for XX +; 133 bytes -- undo opt, no lookup table, just raw divide +; 145 bytes -- init stars at beginning, so don't initially run bacward if Z=FF +; 135 bytes -- optimize divide some more COLOR = $30 +NEGATIVE = $F9 QUOTIENT = $FA DIVISOR = $FB DIVIDEND = $FC @@ -21,11 +26,12 @@ XX = $FD YY = $FE FRAME = $FF -oldx = $80 -oldy = $90 -star_x = $A0 -star_y = $B0 -star_z = $C0 +star_z = $60 +oldx = $70 +oldy = $80 +star_x = $90 +star_y = $A0 + ;oldx = $1000 ;oldy = $1040 @@ -39,6 +45,8 @@ LORES = $C056 ; Enable LORES graphics HGR2 = $F3D8 HGR = $F3E2 PLOT = $F800 ; PLOT AT Y,A (A colors output, Y preserved) +NEXTCOL = $F85F +SETCOL = $F864 ; COLOR=A SETGR = $FB40 WAIT = $FCA8 ; delay 1/2(26+27A+5A^2) us @@ -46,59 +54,7 @@ small_starfield: ;0GR:DIMV(64,48):FORZ=1TO48:FORX=0TO64:V(X,Z)=(X*4-128)/Z+20:NEXTX,Z - jsr SETGR - - ; init the X/Z tables - - ldy #63 ; Y==z for(z=1;z<64;z++) { -xloop: - ldx #0 ; X==x -zloop: - lda #$ff - sta QUOTIENT -; stx DIVIDEND - sty DIVISOR - txa ; DIVIDEND -div_loop: - inc QUOTIENT - sec -; lda DIVIDEND - sbc DIVISOR -; sta DIVIDEND - bpl div_loop - - ; write out quotient - - lda QUOTIENT - pha - clc - adc #20 -to_smc: - sta $5F80,X - - inx - bpl zloop ; loop until 128 - - - ; reverse and write out negative parts - - ldx #0 -negative_loop: - pla - eor #$ff - sec - adc #20 -to2_smc: - sta $5F00,X - inx - bpl negative_loop - - dec to_smc+2 - dec to2_smc+2 - - dey - bne xloop - + jsr SETGR ; A is D0 after? ;=================================== ; draw the stars @@ -107,6 +63,14 @@ to2_smc: ; bit LORES ; jsr SETGR +; tax + + ldx #15 +make_orig_stars: + jsr make_new_star + dex + bpl make_orig_stars + ;=================================== ; starloop @@ -115,49 +79,8 @@ big_loop: ldx #15 star_loop: - ;============================== - ; get X/Z - ; X=V(A(P),Z(P)) - - ; position Z - lda star_z,X - clc - adc #$20 ; tables in $20-$5F - sta xload_smc+2 - sta xload2_smc+2 - - ; get XX - ldy star_x,X -xload_smc: - lda $5F00,Y - sta XX - - bmi new_star ; if <0 - cmp #40 - bcs new_star ; bge >40 - - ;============================== - ; get Y/Z - ; Y=V(B(P),Z(P)) - - ; get YY - - ldy star_y,X -xload2_smc: - lda $5F00,Y - sta YY - - bmi new_star ; if <0 - cmp #40 - bcs new_star ; bge >39 - - ;Z(P)=Z(P)-1 - dec star_z,X - beq new_star ; if Z=0 new star - - ; draw the star - -draw_star: + ;=================== + ; erase old ;4 COLOR=0 lda #$00 @@ -169,23 +92,107 @@ draw_star: lda oldy,X jsr PLOT ; PLOT AT Y,A + ;=========================== + ; position Z + +; lda star_z,X +; beq new_star ; should never happen +; sta DIVISOR + + ; DIVISOR always star_z,X + + ;============================== + ; get Y/Z + ; Y=V(B(P),Z(P)) + + ; get YY + + lda star_y,X ; get Y of star + + jsr do_divide + + sta YY ; YY + + bmi new_star ; if <0 + cmp #40 + bcs new_star ; bge >39 + + + ;============================== + ; get X/Z + ; X=V(A(P),Z(P)) + + ; get XX + + lda star_x,X ; get X of start + + jsr do_divide + +; sta XX + tay + + bmi new_star ; if <0 + cpy #40 + bcs new_star ; bge >40 + + ;======================== + ; adjust Z + + ;Z(P)=Z(P)-1 + dec star_z,X + beq new_star ; if Z=0 new star + + ; draw the star + +draw_star: + ; COLOR=15 - dec COLOR + dec COLOR ; color from $00 (black) to $ff (white) + txa + ror + bcs not_far + jsr NEXTCOL + +; ror +; jsr NEXTCOL +; lda #$55 +; sta COLOR ; FF -> 7F +not_far: ;PLOT X,Y ; O(P)=X:Q(P)=Y - ldy XX - sty oldx,X +; ldy XX ; XX already in Y + sty oldx,X ; save for next time to erase - lda YY - sta oldy,X + lda YY ; YY + sta oldy,X ; ;save for next time to erase jsr PLOT ; PLOT AT Y,A - ; a should be F0 or 0F here? - bne done_star + ; a should be F0/20 or 0F/02 here? + bne done_star ; bra new_star: + jsr make_new_star ; + +done_star: + ;7NEXT + + dex + bpl star_loop + + lda #120 + jsr WAIT ; A is 0 after + + ; GOTO2 + beq big_loop ; bra + + + ;=========================== + ; NEW STAR + ;=========================== + +make_new_star: ;IFX<0ORX>39ORY<0ORY>39ORZ(P)<1THEN ; A(P)=RND(1)*64 ; B(P)=RND(1)*64 @@ -195,7 +202,8 @@ new_star: lda $F000,Y sta star_x,X ; random XX - lda $F001,Y +color_lookup: + lda $F100,Y sta star_y,X ; random YY lda $F002,Y @@ -205,21 +213,53 @@ new_star: inc FRAME + rts -done_star: - ;7NEXT + ;============================= + ; do divide + ;============================= + ; Z is in divisor + ; x/y is in A - dex - bpl star_loop +do_divide: + ; A was just loaded so flags still valid + php + bpl not_negative - lda #100 - jsr WAIT ; A is 0 after + eor #$ff + clc + adc #1 ; invert + +not_negative: + + ldy #$ff ; QUOTIENT +div_loop: + iny ; inc QUOTIENT + sec + sbc star_z,X ; DIVIDEND=DIVIDEND-DIVISOR + bpl div_loop + + ; write out quotient + tya ; lda QUOTIENT + + plp + bpl pos_add + + eor #$ff + sec + bcs do_add + +pos_add: + clc +do_add: + adc #20 + +early_out: + rts - ; GOTO2 - beq big_loop ; bra ; for BASIC bot load ; need this to be at $3F5 - + ; it's at 8A, so 6B jmp small_starfield diff --git a/graphics/gr/starfield/starbot_lookup.s b/graphics/gr/starfield/starbot_lookup.s new file mode 100644 index 00000000..4c7d9973 --- /dev/null +++ b/graphics/gr/starfield/starbot_lookup.s @@ -0,0 +1,235 @@ +; starfield tiny -- Apple II Lores + +; by Vince `deater` Weaver + +; actually too fast + +; 189 bytes - original +; 184 bytes - move DIVIDEND to A +; 173 bytes - move variables to 0 page. limits to 16 stars but that's fine? +; 171 bytes - adjust random # generator +; 170 bytes - can do sty zp,x +; 163 bytes - lose the cool HGR intro +; 161 bytes - re-arrange RNG location +; 158 bytes - ra-arrange a lot to remove need for XX + +COLOR = $30 + +QUOTIENT = $FA +DIVISOR = $FB +DIVIDEND = $FC +XX = $FD +YY = $FE +FRAME = $FF + +oldx = $80 +oldy = $90 +star_x = $A0 +star_y = $B0 +star_z = $C0 + +;oldx = $1000 +;oldy = $1040 +;star_x = $2000 ; should be 0, not used as we never /0 +;star_y = $2040 +;star_z = $2080 + + +LORES = $C056 ; Enable LORES graphics + +HGR2 = $F3D8 +HGR = $F3E2 +PLOT = $F800 ; PLOT AT Y,A (A colors output, Y preserved) +SETGR = $FB40 +WAIT = $FCA8 ; delay 1/2(26+27A+5A^2) us + +small_starfield: + + ;0GR:DIMV(64,48):FORZ=1TO48:FORX=0TO64:V(X,Z)=(X*4-128)/Z+20:NEXTX,Z + + jsr SETGR + + ; init the X/Z tables + + ldy #63 ; Y==z for(z=1;z<64;z++) { +xloop: + ldx #0 ; X==x +zloop: + lda #$ff + sta QUOTIENT +; stx DIVIDEND + sty DIVISOR + txa ; DIVIDEND +div_loop: + inc QUOTIENT + sec +; lda DIVIDEND + sbc DIVISOR +; sta DIVIDEND + bpl div_loop + + ; write out quotient + + lda QUOTIENT + pha + clc + adc #20 +to_smc: + sta $5F80,X + + inx + bpl zloop ; loop until 128 + + + ; reverse and write out negative parts + + ldx #0 +negative_loop: + pla + eor #$ff + sec + adc #20 +to2_smc: + sta $5F00,X + inx + bpl negative_loop + + dec to_smc+2 + dec to2_smc+2 + + dey + bne xloop + + + ;=================================== + ; draw the stars + ;=================================== + +; bit LORES +; jsr SETGR + + ;=================================== + ; starloop + + ;2FORP=0TO5 +big_loop: + ldx #15 +star_loop: + + ;=================== + ; erase old + + ;4 COLOR=0 + lda #$00 + sta COLOR + + ;PLOT O(P),Q(P) + + ldy oldx,X + lda oldy,X + jsr PLOT ; PLOT AT Y,A + + ;=========================== + ; position Z + + lda star_z,X + clc + adc #$20 ; tables in $20-$5F + sta xload_smc+2 + sta xload2_smc+2 + + ;============================== + ; get Y/Z + ; Y=V(B(P),Z(P)) + + ; get YY + + ldy star_y,X ; get Y of star +xload2_smc: + lda $5F00,Y ; lookup Y/Z + sta YY ; YY + + bmi new_star ; if <0 + cmp #40 + bcs new_star ; bge >39 + + + ;============================== + ; get X/Z + ; X=V(A(P),Z(P)) + + ; get XX + ldy star_x,X ; get X of start +xload_smc: + lda $5F00,Y ; lookup X/Z + tay ; XX + + bmi new_star ; if <0 + cpy #40 + bcs new_star ; bge >40 + + ;======================== + ; adjust Z + + ;Z(P)=Z(P)-1 + dec star_z,X + beq new_star ; if Z=0 new star + + ; draw the star + +draw_star: + + ; COLOR=15 + dec COLOR ; color from $00 (black) to $ff (white) + + ;PLOT X,Y + ; O(P)=X:Q(P)=Y + +; ldy XX ; XX already in Y + sty oldx,X ; save for next time to erase + + lda YY ; YY + sta oldy,X ; ;save for next time to erase + jsr PLOT ; PLOT AT Y,A + + ; a should be F0 or 0F here? + bne done_star ; bra + +new_star: + ;IFX<0ORX>39ORY<0ORY>39ORZ(P)<1THEN + ; A(P)=RND(1)*64 + ; B(P)=RND(1)*64 + ; Z(P)=RND(1)*48+1:GOTO7 + + ldy FRAME + lda $F000,Y + sta star_x,X ; random XX + + lda $F001,Y + sta star_y,X ; random YY + + lda $F002,Y + and #$3f ; random ZZ 0..63 + ora #$1 ; avoid 0 + sta star_z,X + + inc FRAME + + +done_star: + ;7NEXT + + dex + bpl star_loop + + lda #100 + jsr WAIT ; A is 0 after + + ; GOTO2 + beq big_loop ; bra + + ; for BASIC bot load + + ; need this to be at $3F5 + + jmp small_starfield