Sluníčko by Řrřola [web]
; \|/ Slunicko
;>=O=< a 256-byte intro by rrrola <rrrola@gmail.com>
; /|\ greets to everyone who's ever got a bad sunburn
org 100h ; assume cs<=0x4000 ax=0 sp=di=-2 si=0x100
; macros to access constants
%define w(xx) word[byte bp+si-0x100+xx]
%define d(xx) dword[byte bp+si-0x100+xx]
push ax ; push zero for "ret"
push 0xa000 ; screen segment
mov ax,0x4f02 ; set VESA mode
;Run through a few constants.
;ab stosw ; di=0
;3f aas
;22c2 and al,dl
;b7a3 mov bh,0xa3
;b783 mov bh,0x83
;bb0e01 mov bx,0x10e ; mode 320x200 with 65536 colors
SMUL equ $-2 ; 1.34
db 0xab,0x3f
AMUL equ $-2 ; -40.56 ~ -128/pi (-40.74)
db 0x22,0xc2
XMUL equ $-3 ; -2.314e-5 ~ -2.441e-5 (320/256 / (256*200))
db 0xb7
YMUL equ $-2 ; -1.952e-5 ~ -1.953e-5 (1 / (256*200))
db 0xa3,0xb7
CMUL equ $-2 ; -0.004
db 0x83,0xbb
dw 0x010e
int 10h ; set mode 320x200 with 65536 colors
RMUL equ $-1 ; 1808
pop es ; es = screen segment
lds bx,[si-3] ; bx = 0, ds = 0x5000 texture segment
;Generate 2D Brownian motion texture
; bx=count si=adr bp,dx,cx=random generator
; similar to baze's texture generator, used in Terén
M:
T lodsb ; al = top right texel
dec bp ; do some pseudorandom stuff
ror bp,cl
xor dx,bp
sar dx,3
adc cx,dx ; ch += random (-16..16)
adc ch,al ; ch += top right texel
rcr cx,1
mov [si+254],ch ; store texel
dec bx
jnz T ; loop 512x (65536x on init)
pusha ; we'll do more texture generation later
mov cx,si ; ch=time (texture offset)
xor bp,bp ; bp=0, si=0x100 (nice values)
mov si,0x100
;Pixel loop: di=pixel address if the buffer was 8-bit
X mov ax,0xcccd ; convert width 320->65536 (from Tetraskelion)
mul di
xchg ax,bx ; full 16-bit precision of X
mov ax,0x4f05
add bx,ax
adc dx,0x9b80 ; center at [100, 159.5]: should be 0x9b804d46
pusha ;{di si bp sp bx dx cx ax} to the stack
; YY Y = [-8-18]
; X X X = [-9-18]
;Is it time to switch the VESA bank?
add di,di ; switch when pixel address = 0
jnz D
cwd
adc dx,dx ; dx=page (0 or 1)
xor bx,bx ; bh=0 (set bank), bl=0 (window id)
int 10h ; assume 64kB granularity and window at 0xA000
;Build a (5,6,5)-bit pixel: approximate sRGB with [√R √G √B]
D call I ; compute color
xor ax,ax
inc ax ; ax=1 cx=6
mov cl,6
P fsqrt ;; 29656*[√R √G √B]
fimul w(BIG) ; store 15-bit color component (0..7fff)
fistp word[bp+si] ; if it's > 0x7fff, clamp to 0x8000
imul bx,[bp+si],2 ; double, set carry if it was > 0x3fff
sbb bx,bp ; clip overflow (0x8000*2) to 0xffff
xor cl,5^6 ; shift lengths: [5 6 5]
shld ax,bx,cl ; rrrrrggggggbbbbb: shift into ax
BIG: equ $-1 ; 29656
jnc P ; loop 3x until you've shifted the 1 bit out of ax
stosw
popa
inc di
jnz X ; loop 65536x, di=0
popa
mov bh,2 ; advance time: the texture cycles every 128 frames
;Exit on ESC
in al,60h
cbw
dec ax
jne M ; loop until ESC
mov al,3 ; textmode
int 0x10 ; use "ret" from below
;Subroutine: compute color.
; using a subroutine saves a byte: +3 call, -4 main loop jumps
I fild word[bp-8-18]
fmul d(YMUL)
fild word[bp-9-18]
fmul d(XMUL) ;; x=X/(320*200) y=Y/(256*200) ; y:-1..1
add dh,ch ; texture coords for background:
add dh,0x80 ; dl = u = x
push dx ; dh = v = y+time
;Polar coordinates (from Polar Beat)
fld st1 ;; y x y
fpatan ;; a=atan(x/y) y ; a:-π..π, 0=vertical
fld st0
fcos ;; cos(a) a y
fdivp st2,st0 ;; a r=y/cos(a) ; r=√(x²+y²)
fmul d(AMUL) ;; A=a*-128/π r ; A:-128..128
fistp dword[bp+si]
mov bl,[bp+si]; bl = u texcoord = A
fld st0 ;; 1808/r r ; about 7.06 * 256 / r
fidivr w(RMUL)
fistp dword[bp+si]
mov bh,[bp+si+1] ; t = [bp+si] = bottom bits of R (for later)
add bh,ch ; bh = v texcoord = R+time
;Sun
fmul st0
fld1 ;; 1-r²
fsubrp st1,st0
fmul st0
fmul st0
fmul st0
fmul st0 ;; s=(1-r²)¹⁶
mov cx,2
O fld st0
fmul d(SMUL) ;; R=1.34²*s G=1.34*s B=s
loop O ; loop 2x
;Foreground: tunnel with chromatic aberration and interpolation
mov cl,3 ; Linear interpolation between v and v+1:
F mov al,[bp+si]
not al ; al = 1-t
mul byte[bx]
xchg ax,dx ; dx = (1-t) * tex[u,v] ; 8*8 -> 16bit
inc bh ; chromatic aberration - R:v G:v+1 B:v+2
mov al,[bp+si]
mul byte[bx] ; ax = t * tex(u,v+1)
add ax,dx ; ax = (1-t) * tex[u,v] + t * tex[u,v+1]
shr ax,7 ; foreground is 2x brighter than background
stc
jmp A ; accumulate one color channel, return to R
R loop F ; loop 3x
;Background: scrolling clouds
pop bx ; bx = background texture coordinates
mov cl,3
B dec bh
mov al,[bx] ; keep white stars when ah>0
clc ; don't return to R
; Subroutine: accumulate one color channel: [R G B] += [x² x⁴ x⁸]
A mov [bp+si-2],ax
fild word[bp+si-2]
fmul d(CMUL) ; x = -0.004*ax
push cx
Q fmul st0
loop Q ; loop 1x for R, 2x for G, 3x for B
pop cx
faddp
fstp st3 ;; cycle: R G B -> G B R -> B R G
jc R ; return to R
loop B ; loop 3x
ret
[ back to the prod ]
