Atraktor by Řrřola [web]
; _ _ |/_ _ ; A T R A K T (O) R ; / \ | |\/ \ |\ | |\ ; ;a 256-byte intro by rrrola <@gmail> ;greets to all of you who keep doing these ;mostly bus- and party coding org 100h aas ; db 3Fh: float[si-3] = 0.5 PSCALE: ;=-16256 db 0x80,0xC0,13h ; long "add al,13h" int 10h add dh,al ; ds = cs = ss = constants, stack, scratch mov fs,dx ; teal screen add dh,al mov gs,dx ; orange screen add dh,al mov es,dx ; 32768 stored points (TODO: bytes are enough when normalized correctly) mov bp,SHAPE+1 ; u16[bp]=shape, [bp+si]=scratch mov dx,3c8h ; vintage palette: ttttoooo (teal * orange) salc ; al=0 out dx,al inc dx P:or ax,1100001111000011b push ax out dx,al ; R add al,ah shr al,1 out dx,al ; G add al,ah shr al,2 out dx,al ; B pop ax inc ax jnz P M2: fninit fldz fldz fldz ; {c b a} - previous points of the attractor dec bp ; fst qword[bp+si+4] ; zero MAX and -MIN (didn't make the cut) pop bx M:push di ;=0 (after first frame) ; sp-=2 counts frames (crash after ~30k frames) call I ; combine orange and blue screens, store result to vram, clear them ; di=0, cx=0 push es S:xor ax,ax xchg al,[gs:di] ; xchg reg,mem is slow but small xchg ah,[fs:di] shr ah,4 and al,0xF0 push 0xA000 WIDTH: equ $-1 ;=160 add al,ah pop es stosb loop S ;; fade out ;S:mov dl,0xF0 ; mov al,[gs:di] ; shr byte[gs:di],1 ; and dl,[fs:di] ; shr byte[fs:di],1 ; shr al,4 ; push 0xA000 ;WIDTH: equ $-1 ;=160 ; add al,dl ; pop es ; stosb ; loop S ;; smaller fade out 2 ;S:mov al,0xF0 ; and al,[gs:di] ; shr byte[gs:di],4 ; shr byte[fs:di],4 ; push 0xA000 ;WIDTH: equ $-1 ;=160 ; add al,[fs:di] ; pop es ; stosb ; loop S pop es ; draw all 32768 points with rotation and perspective ; di=0(index into points) mov [bp+si],sp fild word[bp+si] fidiv word[byte si+9] ; {t/ROTATION_SPEED . . .} fsincos ; {s c . . .} fdiv st1,st0 ; {s c/s . . .} D: ;rotate fld st0 ; {s s c/s . . .} fimul word[es:di] ; {s*(x=p[i]) s c/s . . .} fld st0 ; {sx sx s c/s . . .} fmul st3 ; {cx sx s c/s . . .} scasw fld st2 ; {s cx sx s c/s . . .} fimul word[es:di] ; {s*(z=p[i+1]) cx sx s c/s . . .} fadd st1,st0 ; {sz sz+cx sx s c/s . . .} fmul st4 ; {cz sz+cx sx s c/s . . .} fsubrp st2,st0 ; {Z=sz+cx X=cz-sx s c/s . . .} scasw mov al,[es:di+3] ; (color=p[i+3]>>8): -128..127 fiadd word[si] ; {Z+BIG X s c . . .} fiadd word[si] ; {Z+2*BIG X s c . . .} fidivr word[byte si-100h+WIDTH]; {w=WIDTH/(Z+2*BIG) X s c . . .} fmul st1,st0 ; {w X*w s c . . .} fimul word[es:di] ; {(Y=p[i+2])*w X*w s c/s . . .} fistp word[bp+si] ; Y*w {X*w s c . . .} imul bx,[bp+si],320 fistp word[bp+si] ; X*w {s c . . .} jo O ; handle Y overflow add bx,[bp+si] add bx,100*320+160 ; bx = adr = (iy+100)*320 + (ix+160) add al,128 shr al,3 ; 0..31 C:add [fs:bx],al jnc E sub [fs:bx],al ; cheap saturate E: xor al,255>>3 ; 31..0 add [gs:bx],al jnc F sub [gs:bx],al F: O:dec di dec di jnz D ; i++ fcompp ; get rid of rotation coefficients {. . .} ; esc check in al,60h dec ax jnz M ; my custom variation of the Pickover attractor: c,b,a = a*sin(p0*c+p1)+sin(p2*b+p3),c,b ; generate about 500 new points for nice fadeout I:imul bx,sp,512+64 ; where to start overwriting old points: sp decreases by 2 mov ch,512/256+1 R:pusha mov cx,2 ; {c b a} H:fld st1 ; {b c b a} ; {c sin(p0*b+p1) c b a} fimul word[bp+di] ; {p0*b c b a} ; {p2*c sin(p0*b+p1) c b a} ror word[bp+di],4 fiadd word[bp+di] ; {p0*b+p1 c b a} ; {p2*c+p3 sin(p0*b+p1) c b a} ror word[bp+di],4 fidiv word[byte si-100h+PSCALE] fsin ; {sin(p0*b+p1) c b a} ; {sin(p2*c+p3) sin(p0*b+p1) c b a} loop H fmul st4 ; {a*sin(p2*c+p3) sin(p0*b+p1) c b a} faddp st1,st0 ; {a*sin(p2*c+p3)+sin(p0*b+p1) c b a} ffree st3 ; {d=a*sin(p2*c+p3)+sin(p0*b+p1) c b} ; can preserve rest of stack with 2*fxch ; min-max normalization: didn't make the cut ; [B]=MAX=max(d_i), [B+4]=MAX2=max(-d_i) = -min(d_i) ; branchless min: mid = (a+b)/2; radius = abs(a-b)/2; max = mid+radius ; the qword zero store is necessary ;; fld st0 ;; fchs ; {-d d . .} ;; mov cl,2 ;;L:add bp,4 ;; fld st1 ; {d -d d . .} ; {-d MAX -d d . .} ;; fadd dword[bp+si]; {d+MAX -d d . .} ; {-d+MAX2 MAX -d d . .} ;; fld st2 ; {d d+MAX -d d . .} ; {-d -d+MAX2 MAX -d d . .} ;; fsub dword[bp+si]; {d-MAX d+MAX -d d . .} ; {-d-MAX2 -d+MAX2 MAX -d d . .} ;; fabs ; {abs(d-MAX) d+MAX -d d . .} ; {abs(-d-MAX2) -d+MAX2 MAX -d d . .} ;; faddp st1,st0 ; {2*max(d,MAX) -d d . .} ; {2*max(-d,MAX2) MAX -d d . .} ;; fmul dword[si-3]; {MAX=max(d,MAX) -d d . .} ; {MAX2=max(-d,MAX2) MAX -d d . .} ;; fst dword[bp+si]; {MAX -d d . .} ; {-MIN=MAX2 MAX -d d . .} ;; loop L ;; ;;; normalize ;; fadd st1,st0 ; {-MIN MAX-MIN -d . . .} ;; fsubrp st2,st0 ; {MAX-MIN d-MIN . . .} ;; fdivp st1,st0 ; {d(0..1)=(d-MIN)/(MAX-MIN) . . .} ;; fadd st0 ; {d(0..2) . . .} ;; fimul word[si] ; {d(0..2*BIG) . . .} ;; fisub word[si] ; {d(-BIG..BIG) . . .} ; no normalization, larger, messier fld st0 ; 0..1 -> -12k..12k fimul word[si+6] fisub word[si+0x17] fistp word[es:bx] popa inc bx inc bx loop R jz M2 ; switch to the next attractor if we hit 0 = every 170 frames ; the jump was after "I:imul", but zero flag after imul is undocumented! ret ; parameters (words) that work nicely together even when stepping by bytes ; will overflow into code, nobody cares ;db 0x98, 0x67, 0xfc db 0xbb, 0x77, 0xfc, 0x9c, 0xfe, 0x65, 0xBD, 0x58, 0x7C, 0xA1, 0x78 db 0x06, 0x5C, 0x8B, 0xEB, 0x7C ;db 0x08, 0x80, 0x5F, 0xC6 SHAPE: equ $-2
[ back to the prod ]