pouët.net

Go to bottom

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
Go to top