; bubble universe tiny -- Apple II Lores ; what if you zoom into a bubble universe and it's full of ; angry bees ; by Vince `deater` Weaver ; this version based on fast c64 code by serato_fig ; as posted to the sizecoding discord ; based on his TIC-80 variant ; originally was working off the BASIC code posted on the pouet forum ; original effect by yuruyrau on twitter ; 578 bytes = original color ; 531 bytes = remove keyboard code ; 527 bytes = inline sine gen ; 523 bytes = optimize init a bit ; 301 bytes = generate color lookup table ; 297 bytes = optimize color lookup table ; 282 bytes = optimize color shift ; 266 bytes = reduce resolution of sine table x2 ; 260 bytes = shave off some bytes with unneeded compares ; 255 bytes = reoptimize the sine doubler ; 264 bytes = add sound (urgh) ; 265 bytes = fix colors ; 263 bytes = waste a lot of time optimizing color lookup table ; soft-switches SPEAKER = $C030 FULLGR = $C052 ; ROM routines PLOT = $F800 ;; PLOT AT Y,A SETGR = $FB40 ; zero page COLOR = $30 SINES_BASE = $C0 I = $D0 J = $D1 T = $D7 U = $D8 V = $D9 IT = $DA IS = $DB INL = $FC INH = $FD sines = $6c00 sines2 = $6d00 ; must be page aligned :( cosines = $6e00 cosines2= $6f00 color_map = $1000 bubble_gr: ;======================= ; init graphics ;======================= jsr SETGR ; can't rely on registers after this as different on IIe ; with 80 col card bit FULLGR ;======================== ; setup lookup tables ;======================== ;======================== ; color lookup ;======================== ; 34 original ; 30 updated ; 31 fixed ; 29 improved ;================ ; current best ldx #0 ; init output pointer ; 2 first_loop: ldy #$ff ; reset current value ; 2 loop1: yloop: iny ; 1 yloop2: tya ; 1 sta color_map,X ; values[y]=a; ; 3 iny ; 1 inx ; 1 beq done ; 2 cpx #16 ; 2 beq first_loop ; 2 txa ; 1 and #$f ; 2 beq yloop ; if nextcol==0, skip f->0 ; 2 lsr ; 1 bne yloop2 ; if nextcol!=1, y=y+1 ; 2 dey ; if nextcol==1, repeat y ; 1 jmp yloop2 ; 3 done: ; X=0 here ;========================== ; make sine/cosine tables ;========================== ; floor(s*sin((x-96)*PI*2/256.0)+48.5); ;=================================== ; ; ; final_sine[i]=quarter_sine[i]; // 0..64 ; final_sine[128-i]=quarter_sine[i]; // 64..128 ; final_sine[128+i]=0x60-quarter_sine[i]; // 128..192 ; final_sine[256-i]=0x60-quarter_sine[i]; // 192..256 setup_sine_table: ; spread sine table ; load from sines_base,Y/2 ; store to SINES_BASE,Y ; ldx #0 ; set previously spread_loop: txa lsr tay lda sines_base,Y sta SINES_BASE,X ; double the output inx cpx #64 bne spread_loop ; ldx #64 ldy #64 setup_sine_loop: lda SINES_BASE,X sta sines,X sta sines2,X sta sines,Y sta sines2,Y lda #$60 sec sbc SINES_BASE,X sta sines+128,X sta sines2+128,X sta sines+128,Y sta sines2+128,Y iny dex bpl setup_sine_loop ; X is $FF here? inx ; ldx #0 cosine_loop: lda sines+192,X sta cosines,X sta cosines2,X inx bne cosine_loop ; X is 0 here? ;======================= ; init variables ;======================= ; ; lda #0 stx U stx V stx T dex ; Y=$FF (color white) stx COLOR ;========================= ;========================= ; main loop ;========================= ;========================= next_frame: ; reset I*T lda T sta it1_smc+1 sta IT ; sta it2_smc+1 ; reset I*S lda #0 sta is1_smc+1 sta IS ; sta is2_smc+1 num1_smc: lda #13 ; 13 sta I i_loop: num2_smc: lda #$18 ; 24 sta J j_loop: ldx U ldy V ; where S=41 (approximately 1/6.28) bit SPEAKER ; click speaker clc ; 2 ; calc: b=i+t+u; ; u=cosines[a]+cosines[b]; lda IS adc V tay lda IT adc U tax ;is2_smc: lda cosines,Y ; 4+ ;it2_smc: adc cosines,Y ; 4+ sta V ; calc: a=i*s+v; ; u=sines[a]+sines[b]; is1_smc: lda sines,Y ; 4+ it1_smc: adc sines,X ; 4+ sta U ; 3 bit SPEAKER ; click speaker ;=========================================================== ; original code is centered at 96,96 (on hypothetical 192x192 screen) ; we adjust to be 40x48 window centered at 48,48 ; PLOT U-48,V-48 ; U already in A ; sec sbc #48 tay ; 2 cpy #40 bcs no_plot ; calculate Ypos lda V ; sec sbc #48 cmp #48 bcs no_plot bit SPEAKER ; click speaker jsr PLOT ; PLOT AT Y,A no_plot: dec J bne j_loop done_j: lda is1_smc+1 clc adc #41 ; 1/6.28 = 0.16 = 0 0 1 0 1 0 0 0 = 0x28 sta is1_smc+1 ; sta is2_smc+1 sta IS dec I bne i_loop done_i: ; sty V inc T end: ;================= ; cycle colors ldy #$0 ; 2 sty INL ; 2 lda #4 ; 2 sta INH ; 2 cycle_color_loop: lda (INL),Y ; 2 tax ; 1 lda color_map,X ; 3 sta (INL),Y ; 2 iny ; 1 bne cycle_color_loop ; 2 ; need to do this for pages 4-7 inc INH ; 2 lda INH ; 2 cmp #$8 ; 2 bne cycle_color_loop ; 2 ; beq next_frame ; bra ; 2 jmp next_frame ; half as many points sines_base: .byte $30,$32,$34,$36,$38,$3A,$3C,$3E .byte $40,$42,$43,$45,$47,$48,$4A,$4C .byte $4D,$4E,$50,$51,$52,$53,$54,$55 .byte $56,$57,$57,$58,$58,$59,$59,$59 .byte $59 ; floor(s*cos((x-96)*PI*2/256.0)+48.5);