Gyroid by Řrřola [web]
; | | | | | | | | | | |
; +--+ +--+ +--+ +--+ +--+ +--
; / \ / \ / \ / \ / \ /
;--+ Gyroid +--+ +--+ +--+ +--+
; | a 128-byte intro by rrrola <rrrola@gmail.com>
;--+ greets to everyone who's twisted their ankle
; \ / \ / \ / \ / \ / \
; +--+ +--+ +--+ +--+ +--+ +--
; | | | | | | | | | | |
org 100h ; assume ah=bx=[-2]=0 si=0x100 di=sp=-2 [0xfd..ff]=0
;68 f6 9f
push 0xa000 - 160/16
lds bp,[si-3]; bp=0, ds=0x6800: sin table segment
mov al,0x13
;Palette: red and orange gradients
P int 0x10 ; set 320x200 mode (on init) or palette color
xor cx,cx
shrd dx,bx,9 ; bl=index, dh=index/2, dl=(index+1)/4
jc Q ; if index%4<=1 then ch=dl: orange
xchg dl,ch ; else ch=0: red
Q mov ax,0x1010; set palette color: bl=index dh=R ch=G cl=B
dec bx
jnz P ; bx=0
;Sin table with 16384 entries (for speed)
fninit
S mov bx,[bp+di] ; bx=[ss:bp+di]=[ss:-2]=angle (0 on init)
fild word[bp+di]
fidiv word[byte bp+si-0x100+K]
fsin ;| sin(angle/65536*2pi): adjust period to 2*pi
fstp dword[bx]
add [bp+di],sp ; next angle (sp=-4)
jnz S ; bx=4
pop es ; es=0x9ff6: centered screen segment
;For each pixel: initialize ray position X,Y,Z and direction dX,dY,dZ
M mov ax,0xcccd
mul di ; di=pixel address
;96 ; distance factor: float32(-0.21552)=0xbe5cb196
F xchg ax,si ; ax=X=0x3d28 (not on init)
;b1 5c
mov cl,92 ; cl = 4 * 23(number of iterations)
;be 28 = 10430 ~ 65536/2pi
K mov si,0x3d28; si=0x3d28 (exact sin->cos phase would be 0x4000)
sub dh,cl ; dx=dY (centered), dl:bh=dX, cl:dh=dZ=0x5c??
pusha ; stack:[-9 -8 -7 -6 -5 -4 -3]
; bh dl dh cl ch al ah
; ( dY )
; ( dX )( dZ )
cwd ; ax=X=0x3d28, dx=Y=0, bx=Z=time: orange helix
;Compute the distance to the gyroid
G fld dword[bx+si]
xchg ax,dx ;| cosZ | cosY | cosX
xchg ax,bx ; cycle: ax=X dx=Y bx=Z -> ax=Z dx=X bx=Y
fmul dword[bx]
inc bp ;| cosZ*sinY | cosY*sinX | cosX*sinZ
jpo G ; bp=3: loop thrice
faddp
faddp ;| d=cosZ*sinY+cosY*sinX+cosX*sinZ
fist word[bp-7]; [-4](pushed ax) = round(d): +1 or -1
fabs ;| |d|
fldl2e
fsubp st1,st0;| |d|-1.442695
fmul dword[bp-3+F] ;| D=0.21552*(1.442695-|d|)
;Advance the ray position by the distance
A fild word[bp-10]
fmul st1 ;| dZ*D D | dY*D D | dX*D D
fistp word[bp+si]
xchg ax,dx
xchg ax,bx ; cycle: ax=X dx=Y bx=Z -> ax=Z dx=X bx=Y
add ax,[bp+si]; Z+=dZ*D | Y+=dY*D | X+=dX*D
and al,0xfc ; align to a multiple of 4 (for the sin table)
dec cx ; cx-=3
dec bp
jnz A ; bp=0 ("loopnz" would save a byte but it's slow)
;Close enough?
fstp dword[bp+si]
cmp [bp+si+2],si
jl T ; hit if D<0.041 (= signed_bits_float32(D)<0x3d280000)
loop G ; max 23 iterations
;Add texture, draw pixel
T and ah,0xc ; wood-like stripes perpendicular to x
add cl,ah
add [bp-4],cx; [-4](pushed ax) += number of iterations
inc di ; set zero flag
popa
stosb ; al=color
jnz M
;Next frame
inc bh ; time++ (slower)
; add bh,bl ; time+=4 (faster)
jmp M ; loop forever
; in al,0x60 ; esc check
; dec ax
; jnz M
; ret
[ back to the prod ]
