diff --git a/basic/appleiibot/Makefile b/basic/appleiibot/Makefile index b21f8de9..fb44ce46 100644 --- a/basic/appleiibot/Makefile +++ b/basic/appleiibot/Makefile @@ -16,7 +16,8 @@ appleiibot.dsk: E2.BAS FLAME.BAS FLAME2.BAS HELLO \ C64.BAS SIERPINSKI.BAS FAKES.BAS SIER.BAS DROPS.BAS RR.BAS RR_HGR.BAS \ COMBO.BAS WIRES.BAS PATTERN.BAS BALL.BAS LINES.BAS MOD9.BAS \ XOR_ZOOM.BAS MOD9_HGR.BAS SIER_HGR.BAS MOVE.BAS SINE.BAS XDRAW128.BAS \ - GATOR.BAS CURSOR.BAS STARGATE.BAS TUNNEL.BAS STARFIELD.BAS + GATOR.BAS CURSOR.BAS STARGATE.BAS TUNNEL.BAS STARFIELD.BAS \ + STAROOPS.BAS # cp $(EMPTY_DISK)/empty.dsk appleiibot.dsk cp empty.dsk appleiibot.dsk @@ -86,6 +87,7 @@ appleiibot.dsk: E2.BAS FLAME.BAS FLAME2.BAS HELLO \ $(DOS33) -y appleiibot.dsk SAVE A STARGATE.BAS $(DOS33) -y appleiibot.dsk SAVE A TUNNEL.BAS $(DOS33) -y appleiibot.dsk SAVE A STARFIELD.BAS + $(DOS33) -y appleiibot.dsk SAVE A STAROOPS.BAS #### @@ -274,6 +276,11 @@ TUNNEL.BAS: tunnel.bas STARFIELD.BAS: starfield.bas $(TOKENIZE) < starfield.bas > STARFIELD.BAS +#### + +STAROOPS.BAS: staroops.bas + $(TOKENIZE) < staroops.bas > STAROOPS.BAS + #### diff --git a/basic/appleiibot/staroops.bas b/basic/appleiibot/staroops.bas new file mode 100644 index 00000000..1fb38613 --- /dev/null +++ b/basic/appleiibot/staroops.bas @@ -0,0 +1,2 @@ +1FORI=0TO131:POKE884+I,4*PEEK(2125+I)-192+(PEEK(2257+I/3)-35)/4^(I-INT(I/3)*3):NEXT +2&",clU68V.b*lX.V7,fnV/Qh]\+d0FGb`\:b0T0OoQK]P7g/JPZUDe0l2aiQnVQWoX08=kYnC`,7a.b4X:^Rn^,kUS^0kU\\0l3N2/U0foH.31?o6I0Xob>m04nV:./Bo6H7J0S1PKFS4'W4#$G43*#%-%I#F#6.F?3'(,@(130(&$%;&S diff --git a/graphics/hgr/starfield/Makefile b/graphics/hgr/starfield/Makefile index c987661e..b2c9f430 100644 --- a/graphics/hgr/starfield/Makefile +++ b/graphics/hgr/starfield/Makefile @@ -7,12 +7,14 @@ EMPTY_DISK = ../../../empty_disk all: starfield.dsk -starfield.dsk: HELLO STARS FASTAR STARBOT +starfield.dsk: HELLO STARS FASTAR STARBOT STARTINY STAROOPS cp $(EMPTY_DISK)/empty.dsk starfield.dsk $(DOS33) -y starfield.dsk SAVE A HELLO $(DOS33) -y starfield.dsk BSAVE -a 0x0300 STARS $(DOS33) -y starfield.dsk BSAVE -a 0x0C00 FASTAR $(DOS33) -y starfield.dsk BSAVE -a 0x0C00 STARBOT + $(DOS33) -y starfield.dsk BSAVE -a 0x0C00 STARTINY + $(DOS33) -y starfield.dsk BSAVE -a 0x0374 STAROOPS ### @@ -44,6 +46,23 @@ STARBOT: starbot.o starbot.o: starbot.s ca65 -o starbot.o starbot.s -l starbot.lst +### + +STARTINY: startiny.o + ld65 -o STARTINY startiny.o -C $(LINKER_SCRIPTS)/apple2_c00.inc + +startiny.o: startiny.s + ca65 -o startiny.o startiny.s -l startiny.lst + +### + +STAROOPS: staroops.o + ld65 -o STAROOPS staroops.o -C $(LINKER_SCRIPTS)/apple2_374.inc + +staroops.o: staroops.s + ca65 -o staroops.o staroops.s -l staroops.lst + + ### diff --git a/graphics/hgr/starfield/starbot.s b/graphics/hgr/starfield/starbot.s index 233a788f..7935553b 100644 --- a/graphics/hgr/starfield/starbot.s +++ b/graphics/hgr/starfield/starbot.s @@ -3,17 +3,27 @@ ; by Vince `deater` Weaver ; 139 bytes -- lores version +; 157 bytes -- initial hires +; 155 bytes -- scale to more of full screen +; 153 bytes -- blue/orange instead of purple/green +; 149 bytes -- optimize 2nd plot arg shuffling +NUMSTARS = 27 ; 27 good, 28+ not work ($1C) ; zero page locations -COLOR = $30 +star_z = $00 -star_z = $60 -oldx = $70 -oldy = $80 +HGR_BITS = $1C + +; 1C-40 has some things used by hires + +oldx = $50 +oldy = $70 star_x = $90 -star_y = $A0 +star_y = $B0 + +; D0+ used by HGR routines HGR_COLOR = $E4 HGR_PAGE = $E6 @@ -39,13 +49,14 @@ PLOT = $F800 ; PLOT AT Y,A (A colors output, Y preserved) NEXTCOL = $F85F ; COLOR=COLOR+3 SETCOL = $F864 ; COLOR=A SETGR = $FB40 ; set graphics and clear LO-RES screen +BELL2 = $FBE4 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 HGR ; A is ? after + jsr HGR2 ; A is ? after ;=================================== ; draw the stars @@ -54,7 +65,7 @@ small_starfield: ; there are ways to skip this, but on real hardware there's ; no guarantee star_z will be in a valid state, so waste the bytes - ldx #15 + ldx #NUMSTARS make_orig_stars: jsr make_new_star dex @@ -66,14 +77,16 @@ make_orig_stars: ;2FORP=0TO15 big_loop: - ldx #15 + ldx #NUMSTARS ; really tried hard not to have to set this value ; hard to judge best value for this - lda #80 - jsr WAIT -; jsr $FBE4 ; BEEP delays too +; lda #100 +; jsr WAIT + + ldy #30 + jsr BELL2 ; BEEP delays too ; A now 0 @@ -87,11 +100,13 @@ star_loop: lda #$00 ; color to black sta HGR_COLOR ; set HGR_COLOR to value in X - ;PLOT O(P),Q(P) + ;HPLOT O(P),Q(P) stx SAVEX - ldy oldx,X + ldy oldx,X ; get X valu into Y +; tya +; tax sty TEMP lda oldy,X ldx TEMP @@ -120,14 +135,19 @@ star_loop: lda star_y,X ; get Y of star jsr do_divide + adc #96 ; if off-screen then need new star - bmi new_star ; if <0 - cmp #40 + cmp #192 bcs new_star ; bge >39 + cmp #0 + bcc new_star ; if <0 + sta YY ; YY + sta oldy,X ; ;save for next time to erase + ;============================== ; get X/Z @@ -138,14 +158,16 @@ star_loop: lda star_x,X ; get X of start jsr do_divide + adc #128 tay ; put XX in Y + sty oldx,X ; save for next time to erase ; if offscreen then draw new star - bmi new_star ; if <0 - cpy #40 - bcs new_star ; bge >40 +; bmi new_star ; if <0 +; cpy #40 +; bcs new_star ; bge >40 ;======================== ; adjust Z @@ -158,8 +180,11 @@ star_loop: draw_star: - lda #$7f ; white (with green/purple highlights) - sta HGR_COLOR ; set HGR_COLOR to value in X +; lda #$7f ; white (with green/purple highlights) +; sta HGR_COLOR ; set HGR_COLOR to value in X + + dec HGR_COLOR ; smaller, but blue/orange highlights + ;=========================== ; actually plot the star @@ -169,16 +194,10 @@ draw_star: stx SAVEX + tya ; XX in Y + tax ; XX now in X + lda YY ; YY - sta oldy,X ; ;save for next time to erase - -; ldy XX ; XX already in Y - sty oldx,X ; save for next time to erase - - sty TEMP - ldx TEMP - - lda YY ldy #0 @@ -220,7 +239,7 @@ color_lookup: sta star_y,X ; random YY lda $F002,Y - and #$3f ; random ZZ 0..63 + and #$7f ; random ZZ 0..127 (can't go negative or stars move backward) ora #$1 ; avoid 0 sta star_z,X @@ -266,7 +285,7 @@ div_loop: pos_add: clc do_add: - adc #20 ; pre-adjust to have star origin mid screen + early_out: rts diff --git a/graphics/hgr/starfield/staroops.s b/graphics/hgr/starfield/staroops.s new file mode 100644 index 00000000..5d3a6a4e --- /dev/null +++ b/graphics/hgr/starfield/staroops.s @@ -0,0 +1,298 @@ +; starfield tiny -- Apple II Hires + +; by Vince `deater` Weaver + +; 139 bytes -- lores version +; 157 bytes -- initial hires +; 155 bytes -- scale to more of full screen +; 153 bytes -- blue/orange instead of purple/green +; 149 bytes -- optimize 2nd plot arg shuffling + +NUMSTARS = 27 ; 27 good, 28+ not work ($1C) + +; zero page locations + +star_z = $00 + +HGR_BITS = $1C + +; 1C-40 has some things used by hires + +oldx = $50 +oldy = $70 +star_x = $90 +star_y = $B0 + +; D0+ used by HGR routines + +HGR_COLOR = $E4 +HGR_PAGE = $E6 + +SAVEX = $F8 +TEMP = $F9 +QUOTIENT = $FA +DIVISOR = $FB +DIVIDEND = $FC +XX = $FD +YY = $FE +FRAME = $FF + +; soft-switches + +; ROM routines + +HGR2 = $F3D8 ; set hires page2 and clear $4000-$5fff +HGR = $F3E2 ; set hires page1 and clear $2000-$3fff +HPLOT0 = $F457 ; plot at (Y,X), (A) +HCOLOR1 = $F6F0 ; set HGR_COLOR to value in X +PLOT = $F800 ; PLOT AT Y,A (A colors output, Y preserved) +NEXTCOL = $F85F ; COLOR=COLOR+3 +SETCOL = $F864 ; COLOR=A +SETGR = $FB40 ; set graphics and clear LO-RES screen +BELL2 = $FBE4 +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 HGR2 ; A is ? after + + ;=================================== + ; draw the stars + ;=================================== + + ; there are ways to skip this, but on real hardware there's + ; no guarantee star_z will be in a valid state, so waste the bytes + + ldx #NUMSTARS +make_orig_stars: + jsr make_new_star + dex + bpl make_orig_stars + + ;=================================== + ; starloop + + ;2FORP=0TO15 + +big_loop: + ldx #NUMSTARS + + ; really tried hard not to have to set this value + ; hard to judge best value for this + +; lda #100 +; jsr WAIT + + ldy #30 + jsr BELL2 ; BEEP delays too + + ; A now 0 + +star_loop: + ; X=FF + + ;=================== + ; erase old star + + ;4 COLOR=0 + lda #$00 ; color to black + sta HGR_COLOR ; set HGR_COLOR to value in X + + ;HPLOT O(P),Q(P) + +; stx SAVEX + +; ldy oldx,X ; get X valu into Y +; tya +; tax +; sty TEMP +; lda oldy,X +; ldx TEMP + +; ldy #0 + +; jsr HPLOT0 ; plot at (Y,X), (A) + +; ldx SAVEX + + ;=========================== + ; position Z + +; lda star_z,X +; beq new_star ; should never happen +; sta DIVISOR + + ; DIVISOR always star_z,X so can hard code this in divide routine + + ;============================== + ; get Y/Z + ; Y=V(B(P),Z(P)) + + ; get YY + + lda star_y,X ; get Y of star + + jsr do_divide + adc #96 + + ; if off-screen then need new star + + cmp #192 + bcs new_star ; bge >39 + cmp #0 + bcc new_star ; if <0 + + + sta YY ; YY + sta oldy,X ; ;save for next time to erase + + + ;============================== + ; get X/Z + ; X=V(A(P),Z(P)) + + ; get XX + + lda star_x,X ; get X of start + + jsr do_divide + adc #128 + + tay ; put XX in Y + sty oldx,X ; save for next time to erase + + ; if offscreen then draw new star + +; 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: + +; lda #$7f ; white (with green/purple highlights) +; sta HGR_COLOR ; set HGR_COLOR to value in X + + dec HGR_COLOR ; smaller, but blue/orange highlights + + + ;=========================== + ; actually plot the star + + ;HPLOT X,Y + ; O(P)=X:Q(P)=Y + + stx SAVEX + + tya ; XX in Y + tax ; XX now in X + + lda YY ; YY + + ldy #0 + + jsr HPLOT0 ; plot at (Y,X), (A) + + ldx SAVEX + + jmp done_star ; bra + +new_star: + jsr make_new_star ; + +done_star: + ;7NEXT + + dex + bpl star_loop + + ; GOTO2 + bmi 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 + ; Z(P)=RND(1)*48+1:GOTO7 + + ldy FRAME + lda $F000,Y + sta star_x,X ; random XX + +color_lookup: + lda $F100,Y + sta star_y,X ; random YY + + lda $F002,Y + and #$7f ; random ZZ 0..127 (can't go negative or stars move backward) + ora #$1 ; avoid 0 + sta star_z,X + + inc FRAME + + rts + + ;============================= + ; do signed divide + ; the signed part is the pain + ;============================= + ; Z is in divisor + ; x/y is in A + +do_divide: + ; A was just loaded so flags still valid + php + bpl not_negative + + eor #$ff ; make positive for division + clc ; is this necessary? + adc #1 + +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 ; FIXME: made math inaccurate to save room +; bcs do_add + +pos_add: + clc +do_add: + + +early_out: + rts + + + ; for BASIC bot load + + ; need this to be at $3F5 + ; it's at 81, so 74 + jmp small_starfield diff --git a/linker_scripts/apple2_374.inc b/linker_scripts/apple2_374.inc new file mode 100644 index 00000000..4b70c92a --- /dev/null +++ b/linker_scripts/apple2_374.inc @@ -0,0 +1,12 @@ +MEMORY { + ZP: start = $00, size = $1A, type = rw; + RAM: start = $374, size = $8E00, file = %O; +} + +SEGMENTS { +CODE: load = RAM, type = ro; +RODATA: load = RAM, type = ro; +DATA: load = RAM, type = rw; +BSS: load = RAM, type = bss, define = yes; +ZEROPAGE: load = ZP, type = zp; +}