pouët.net

Koruna by Řrřola [web]

;    _)  "\__   Koruna
;(  ( \___/  ' (crown, treetop, corolla, fermata)
; \___/   \_) a 128-byte intro by rrrola <rrrola@gmail.com>
;  /, \_) / ,
; / \_/ \__/ greets to everyone who's ever planted a tree
;/    \_,

org 100h ; assume ax=0 bx=0 si=0x100 di=-2

TIME:
  cwd         ;99     dx=0
  mov al,0x13 ;b0 13  graphics mode 320x200
  inc di      ;47     t = float[0x100] = 37808.6, eps = 2^(15-23)

; Set 320x200 mode and two-channel palette (4 orange + 4 cyan bits).
ZOOM:
P int 0x10    ;CD 10  on init: set graphics mode, later: set palette
  xchg ax,cx  ;91     <- can be 90 "nop" (for zoom = 1.1255)
  aas         ;3F     zoom = float[0x104] = 1.1333

  mov bp,dx     ; bp=4 after loop
  dec bx        ; next index: 255..1 (0 stays black)
  dec dx
  mov ax,0x1010 ; set palette: bl=index dh=red ch=green cl=blue
  and dx,0x3c3c ; dx: ..RRRR.. ..BBBB.. (easier when decrementing dx)
  mov cx,dx     ; ch=R cl=B
  add ch,cl
  shr cx,1      ; ch=green=(R+B)/2 cl=blue=B/2
  jnz P
                ; cx=dx=0 bx=0xff00 bp=4 di=-1 ax=0x1010
  mov bh,0xa0
  mov es,bx     ; es = screen segment

; Frame loop: advance time and prepare coefficients.
;M inc dword[si]    ; t += 1/256, double speed every 2^23 frames
M inc word[si]     ; t += 1/256, 65536 frames (jump at frame 20325)

  ; Scale * rotation: c = zoom*cos(t), s = zoom*sin(t)
  fld dword[si]    ; t
  fsincos          ; cos(t) sin(t)
  fdiv st1,st0     ; cos(t) s/c    ; assume cos(t) is never exactly 0
  fmul dword[bp+si]; c=cos(t)*zoom s/c
  fstp qword[bx]   ; qword[bx]=c (only the most significant 4 bytes)
  fstp dword[bx]   ; dword[bx]=s/c

  ; Translation: t * sin([U*t, V*t])^2
  fldln2
  db 0x3d ;= cmp ax,0xecd9; cf=1 (ax was 0x1010 or 0x80xx)
U fldlg2  ;D9 EC    ; skip on first run
  fmul dword[si]    ; ln(2)*t = 0.693*t   ; log10(2)*t = 0.301*t
  fsin              ; sin(ln(2)*t)        ; sin(log10(2)*t)
  fmul st0          ; v=t*sin(ln(2)*t)^2  ; u=t*sin(log10(2)*t)^2
  fmul dword[si]
  cmc
  jnc U  ; loop 2x ; u v

; Pixel loop.
L mov ax,0xcccd  ; convert width=320 to width=65536 (-32768..32767)
  mul di     ; but x=0 on the left edge of the screen
  add dx,bx  ; center y
  push dx
  push ax    ; store [-4]=dx=y, [-5]=dl:ah=x
  fild word[bp-4-4] ; y u v
  fild word[bp-4-5] ; x y u v

  xor ax,ax         ; al=loop counter, ah=0

; Iterate (x, y) <- zoom * rotate2D(|x|-u, |y|-v).
I fld st1           ; y x _ u v         ; x sy _ cy u v
  fabs
  fsub st4          ; y=|y|-v x _ u v   ; x=|x|-u sy _ cy u v
  fmul qword[bx]    ; cy x _ u v        ; cx sy _ cy u v
  fst st2           ; cy x cy u v       ; cx sy cx cy u v
  fmul dword[bx]    ; sy x cy u v       ; sx sy cx cy u v
  add al,0x82       ; cycle: 00 82 04 86 08 8a ... 7c fe [80]
  jnc I  ; loop 2x  ;           nc c  nc c  nc ... c  nc  c
  faddp st3,st0     ; sy cx cy+sx u v
  fsubp st1,st0     ; x=cx-sy y=cy+sx u v
  jns I  ; loop 32x
                    ; ax=0x80

; Draw pixel: combine orange and blue channel.
                    ; ax=0x80
S fabs              ; [bx+si]=|x|       ; [bx+si]=|y|
  fistp word[bx+si] ; if it's > 0x7fff, store 0x8000
  imul dx,[bx+si],2 ; double, set carry if it was > 0x3fff
  sbb dh,bl         ; dh -= carry (0xff on overflow)
  shld ax,dx,4      ; accumulate color in al, set sign flag
  pop dx            ; also clean up the stack
  jns S  ; loop 2x
  stosb             ; draw pixel

  loop L ; loop 65536x

  fcompp            ; drop u, v

; Exit on ESC.
  in al,0x60
  cmp al,1
  jne M
  ret