pouët.net

Amaze by Red Sector Inc. [web]

; Amaze                         : 128-byte intro with castle wolfenstein raycasting (fasm 1.70.03/WinXP 5.1.2600)
; credit                        : olivier.poudade.free.fr 2013 aka baudsurfer
; credit                        : inspired by Justin Frankel^Nullsoft's 256-byte intro gaycast (www.1014.org/code)
; greets                        : Adok, Frag, lordKelvin, Pirx, Rudi, sensenstahl, y0bi
; shouts                        : dark bit factory forum users (www.dbfinteractive.com) 
BONUSFLOOR=0                    ; set this flag to 1 to draw floor (adds extra 10 bytes)
         org 100h               ; start binary at psp+256
	 fldz                   ; fpu in : undefined / fpu out : (st0=0)
         fldz                   ; fpu in : (st0=0) / fpu out : (st0=0.0) (st1=0.0)
         lds ax,[bx]            ; ds=ff9fh=a000h-16 ax=20cdh bx=assumed 0
frame:   fiadd word [cs:7]      ; advance value from previous frave / psp+7h=1dfeh
	 fld st0                ; fpu in : (st0=0.0) (st1=0.0) / fpu out : (st0=st1) (st1=0.0) (st2=0.0)
	 fld1                   ; fpu in : (st0=st1) (st1=0.0) (st2=0.0) / fpu out : (st0=1.0) (st1=st2) (st2=0.0) (st3=0.0)
	 mov bp,320             ; set bp to SCREEN_W
	 faddp st3,st0          ; fpu in : (st0=1.0) (st1=st2) (st2=0.0) (st3=0.0) / fpu out : (st0=st1) (st1=0.0) (st2=0.0) / popped st0+st3 
	 mov ax,13h             ; vga chaine mode 320x256x8 / best effort to plug it closest to plotting
	 int 10h                ; vga video bios api also used as clear screen function / best effort to plug it closest to plotting
xloop:   mov byte [si+3],3bh    ; was mov word [si+2],3b44h / 3b44h=15172b from /was fadd dword [cs:ADJ_VA] with ADJ_VA dd 994352038
	 fadd dword [si]        ; st0=viewing angle adjust	
         fld st0                ; fpu in : (st0=st1) (st1=0.0) (st2=0.0) / fpu out : (st0=st1) (st1=st2) (st2=0.0) (st3=0.0)  
         fsincos                ; fpu in : (st0=st1) (st1=st2) (st2=0.0) (st3=0.0) / fpu out : (cos(st0=st1)) (sin(st0=st1)) (st2=st3) (st3=0.0) (st4=0.0)
         mov cx,07e0h           ; 07e0h=2016b=32*63 size of maze
         mov dx,cx              ; dx=saved 32*63 cst for later use 
         fld st4                ; st4=st0
         fld st5                ; st5=st0
raycast: fadd st0,st3           ; fpu in : st0 st1 st2 st3 st0 st0 / fpu out: st0+st3 st1 st2 st3 st4 st5
         fist dword [si]        ; [si] = st0+st3 / si isa previous lower column ender-don't care
         fxch                   ; in : st0+st3 st1 st2 st3 st4 st5 out: st1 st0+st3 st2 st3 st4 st5
         fadd st0,st2           ; in : st1 st0+st3 st2 st3 st4 st5 out: st1+st2 st0+st3 st2 st3 st4
         mov bx,[si]            ; mov bh,[si+1]
         fist dword [si]        ; si=st1+st2
         fxch                   ; in : st1+st2 st0+st3 st2 st3 st4  out: st0+st3 st1+st2 st2 st3 st4
         mov bl,[si+1]          ; lsbyte of maze position
         test byte [gs:bx],4    ; test if map wall flag present as arbitrary bitflag in 1kb bios ivt space
         jnz rayhit             ; if so bail out casting loop
         loop raycast           ; else continue raycast           
rayhit:  sub dx,cx              ; dx now holds column height for floor (200-100-lower wall height)
	 mov cx,4               ; disregard scratchpad top 16 bytes of fpu stack 
fpupop16:fstp st0               ; disregard scratchpad top 16 bytes of fpu stack
         loop fpupop16          ; disregard scratchpad top 16 bytes of fpu stack 
         xchg cx,dx             ; after : dx=0, cx=divisor
         mov ah,3bh             ; discreet scale / ah=3bh=>ax=3a98h=15000b 
         div cx                 ; cx=distance / ax=result, dx=remainder
         xchg ax,cx             ; ax=distance, cx=result (wall height/2)
         lea di,[bp+32015]      ; middle of *this column (width*height/2) with ff9fh fixup / di=[32335;32015]
         mov si,di              ; src and dst index are same middle of *this column at start
         mov dx,100             ; dx=max height of wall/2
         cmp cx,dx              ; clipping test 
	 jc texture             ; no clipping needed 
	 mov cl,99              ; clipping
texture: if BONUSFLOOR          ; bonus floor
         sub dx,cx              ; dx=(max column height-wall height)/2
         end if                 ; bonus floor 
yloop:   mov ax,cx              ; xor texture : get height as distance
         xor ax,si              ; xor texture : perform unique number xor texture
         aaa                    ; normalize pixel color palette index to [0,15] 
         adc al,16              ; shift pixel color palette index to vga gray gradient [16,31]
         mov [di],al            ; plot upper vertical pixel
         sub di,320             ; get next upper vertical pixel
floor:   mov [si],al            ; plot lower vertical pixel
         add si,320             ; get next lower vertical pixel
         if BONUSFLOOR          ; bonus floor
         jcxz floor2            ; re-use for floor below (skip loop if cx=0)
         end if                 ; bonus floor 
         loop yloop             ; repeat until all pixels of *this column wall processed
         if BONUSFLOOR          ; bonus floor
         mov al,23              ; discreet uniform grey color value
floor2:  dec dx                 ; decrement *this column floor index
         jnz floor              ; repeat until all pixels of *this column floor processed
         end if                 ; bonus floor 
         dec bp                 ; decrement screen column index
         jnz xloop              ; repeat until all columns [319,0] of this screen processed 
         fstp st0               ; disregard scratchpad top 4 bytes of fpu stack
         jmp frame              ; process next frame / sorry no space left for esc key exit test