home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Party 1994: Try This At Home
/
disk_image.bin
/
source
/
landscap
/
landscap.asm
< prev
next >
Wrap
Assembly Source File
|
1994-12-10
|
13KB
|
794 lines
; =============================================================================
;
; landscapes with *real* shading.
;
; (C)94 xToto/Valhalla
;
; first presented at the pc-party in herning/denmark
;
; =============================================================================
.model large
.stack 100h
Xsin_base = 8 ; we get sin_values values in 0..pi/2
Xsin_values = 1 shl Xsin_base
Xlayers = 13
_data segment public 'data'
Xstart dw 0h+200h, 1f8h+200h, -208h+200h, -400h+200h
Xcolsk dw 4h, 200h, -4h, -200h
Xrowsk dw 4h, 1fch, -4h, -1fch
Xvga dw 003d4h
dw 00e11h
dw 00d06h
dw 03e07h
dw 0c109h
dw 0ea10h
dw 0df12h
dw 02813h
dw 0e715h
dw 00616h
dw -1
dw -1
Xpoint0 dw 03e00h, -03e00h
dw 03e00h, 03e00h
dw -03e00h, 03e00h
dw -03e00h, -03e00h
Xphase dw 0
Xtimer dw 0
Xsrand dw 31237
Xoffset dw 0
Xsun_x db ?
Xsun_y db ?
Xsun_z db ?
Xdx dw ?
Xdx3 dw ?
Xddx dw ?
Xdy dw ?
Xdy3 dw ?
Xddy dw ?
Xx0 dw ?
Xx1 dw ?
Xx2 dw ?
Xx3 dw ?
Xy0 dw ?
Xy1 dw ?
Xy2 dw ?
Xy3 dw ?
Xh1 dw ?
Xh2 dw ?
Xh3 dw ?
Xsins dw Xsin_values dup (?)
Xcoss dw Xsin_values dup (?)
Xsins2 dw Xsin_values dup (?)
Xcoss2 dw Xsin_values dup (?)
Xsins3 dw Xsin_values dup (?)
Xfstart dw Xlayers dup (?)
Xfdx dw Xlayers dup (?)
Xfdy dw Xlayers dup (?)
Xhght1 dd 128 dup (?)
Xhght2 dd 128 dup (?)
_data ends
_landscape segment public 'bss'
dw 08000h dup (?)
_landscape ends
_buffer segment public 'bss'
dw 08000h dup (?)
_buffer ends
_fastmul segment public 'bss'
dw 08000h dup (?)
_fastmul ends
_sun segment public 'code'
assume cs:_sun; ds:_data; es:_landscape; fs:_buffer; gs:nothing
.386
; clean up what needs to be cleaned up
; used registers: ax
Xclean_up:
mov ax, 0003h
int 10h
ret
; build the landscape (draw it into fs)
; used registers: all ?
Xbuild:
mov ax, seg _fastmul ; use mul-lookup
mov gs, ax
mov bx, Xphase
add bx, bx
mov ax, Xstart[bx]
add ax, Xoffset
mov word ptr cs:Xbuild_start-2, ax
mov ax, Xrowsk[bx]
mov word ptr cs:Xbuild_row_skip-2, ax
mov ax, Xcolsk[bx]
mov word ptr cs:Xbuild_col_skip-2, ax
mov al, Xsun_x
mov byte ptr cs:Xbuild_sun_x-1, al
mov al, Xsun_y
mov byte ptr cs:Xbuild_sun_y-1, al
mov al, Xsun_z
mov byte ptr cs:Xbuild_sun_z-1, al
mov ax, Xx2
sub ax, Xx3
mov Xdx, ax
mov bx, Xx1
mov cx, Xx0
sub bx, cx
sub cx, Xx3
sar cx, 6
mov Xdx3, cx
sub bx, ax
sar bx, 6
mov Xddx, bx
mov ax, Xy2
mov dx, Xy3
sub ax, dx
mov Xdy, ax
mov bx, Xy1
mov cx, Xy0
sub bx, cx
sub cx, dx
sar cx, 6
mov Xdy3, cx
sub bx, ax
sar bx, 6
mov Xddy, bx
mov cx, Xx3
add cx, cx
add dx, dx
xor ch, 80h
xor dh, 80h
mov ax, Xdx
mov bx, Xdy
mov di, 1234h
Xbuild_start:
mov bp, 007fh
Xbuild_loop2:
mov ax, Xx3
sub ax, Xx0
imul bp
shrd ax, dx, 7
add ax, Xx0
mov cx, ax
mov ax, Xx2
sub ax, Xx1
imul bp
shrd ax, dx, 7
add ax, Xx1
sub ax, cx
sar ax, 6
mov word ptr cs:[offset Xbuild_inc1 + 2], ax
add cx, cx
add ch, 80h
mov ax, Xy3
sub ax, Xy0
imul bp
shrd ax, dx, 7
add ax, Xy0
mov bx, ax
mov ax, Xy2
sub ax, Xy1
imul bp
shrd ax, dx, 7
add ax, Xy1
sub ax, bx
sar ax, 6
mov word ptr cs:[offset Xbuild_inc2 + 2], ax
mov dx, bx
add dx, dx
add dh, 80h
push bp
mov bp, 007fh
Xbuild_loop1:
mov bh, dh
mov bl, ch
sub bh, es:[di]
mov si, bx
xor bh, bh
mov bl, es:[di+1]
mov al, gs:[bx+0100h]
Xbuild_sun_x:
mov bl, es:[di+2]
add al, gs:[bx+0100h]
Xbuild_sun_y:
mov bl, es:[di+3]
add al, gs:[bx+0100h]
Xbuild_sun_z:
mov ah, al
add di, 1234h
Xbuild_col_skip:
mov fs:[si], ax
mov fs:[si+0100h], ax
mov fs:[si+0200h], ax
mov fs:[si+0300h], ax
mov fs:[si+0400h], ax
Xbuild_inc1:
add cx, 01234h
Xbuild_inc2:
add dx, 01234h
dec bp
jne Xbuild_loop1
add di, 1234h
Xbuild_row_skip:
pop bp
dec bp
jne Xbuild_loop2
ret
; Xdump the buffer to the screen and clear the buffer
; used registers: all ?
Xdump:
mov ax, 0a000h
mov gs, ax
mov si, 68*256+48
xor di, di
mov edx, 80808080h
mov cx, 120
Xdump1:
push cx
mov cx, 80
Xdump2:
mov bx, fs:[si]
mov ah, bh
mov al, bh
shl eax, 16
mov ah, bl
mov al, bl
mov gs:[di], eax
mov fs:[si], dx
add si, 2
add di, 4
dec cx
jnz Xdump2
add si, 96
pop cx
dec cx
jnz Xdump1
ret
; calculate a new row in the fractal (and store it at ds:di)
; used registers: all ?
Xmake_fractal:
mov si, offset Xfstart
mov bp, offset Xfdx
xor eax, eax
mov cx, 20h
Xmake_fractal0:
mov ds:[di], eax
mov ds:[di+4], eax
mov ds:[di+8], eax
mov ds:[di+12], eax
add di, 10h
dec cx
jnz Xmake_fractal0
sub di, 200h
mov cx, Xlayers
Xmake_fractal1:
push cx
mov dx, ds:[bp]
mov bx, [si]
mov cx, 80h
Xmake_fractal2:
movsx eax, Xsins[bx]
add ds:[di], eax
add di, 4
add bx, dx
and bx, 8*Xsin_values-2
dec cx
jnz Xmake_fractal2
sub di, 200h
add si, 2
add bp, 2
pop cx
dec cx
jnz Xmake_fractal1
mov cx, 80h
Xmake_fractal3:
sar dword ptr ds:[di], 5 ; ##
sub word ptr ds:[di], 800h
add di, 4
dec cx
jnz Xmake_fractal3
mov si, offset Xfstart
mov bp, offset Xfdy
mov cx, Xlayers
Xmake_fractal4:
mov ax, ds:[bp]
add ds:[si], ax
and word ptr ds:[si], 8*Xsin_values-2
add bp, 2
add si, 2
dec cx
jnz Xmake_fractal4
ret
; calculate the normals of the landscape
; used registers: all ?
Xget_normals:
mov cx, 0080h
Xget_normals1:
mov ax, ds:[di+4]
sub ax, ds:[di]
mov Xh1, ax
mov ax, -256
mov Xh2, ax
mov ax, ds:[di+200h]
Xget_normals_last:
sub ax, ds:[di]
mov Xh3, ax
movsx eax, Xh1
imul eax
mov esi, eax
movsx eax, Xh2
imul eax
add esi, eax
movsx eax, Xh3
imul eax
add eax, esi
push bx
push cx
push di
call Xsqrt
pop di
pop cx
pop bx
mov si, ax
mov bp, ds:[di]
mov ax, 80h
imul Xh1
idiv si
mov es:[bx+1], al
mov ax, 80h
imul Xh2
idiv si
mov es:[bx+2], al
mov ax, 80h
imul Xh3
idiv si
mov es:[bx+3], al
mov ax, bp
shr ax, 8
mov es:[bx], al
add di, 4
add bx, 4
dec cx
jnz Xget_normals1
neg word ptr cs:Xget_normals_last-2
ret
; Xinitialize everything that needs to be Xinitialized
; used registers: all ?
Xinit:
cld
mov ax, seg _data ; segment registers
mov ds, ax
mov ax, seg _landscape
mov es, ax
mov ax, seg _buffer
mov fs, ax
call Xinit_gfx
call Xinit_sin
call Xinit_buffer
call Xinit_fastmul
call Xinit_fractal
ret
; clear the buffer
; used registers:
Xinit_buffer:
xor di, di
mov edx, 80808080h
Xinit_buffer1:
mov fs:[di], edx
add di, 4
jnz Xinit_buffer1
ret
; Initialize sin-waves for fourier transformation
; used registers: all ?
Xinit_fractal:
mov si, offset Xfstart
mov di, offset Xfdx
mov bp, offset Xfdy
mov cx, Xlayers
Xinit_fractal1:
call Xrand
and ax, 4*Xsin_values-1
add ax, ax
mov [si], ax
call Xrand
and ax, 4*Xsin_values-1
add ax, ax
mov bx, ax
mov ax, Xsins[bx]
sar ax, 10
and ax, -2
mov [di], ax
mov ax, Xcoss[bx]
sar ax, 10
and ax, -2
mov ds:[bp], ax
add si, 2
add di, 2
add bp, 2
dec cx
jnz Xinit_fractal1
mov di, offset Xhght1
xor eax, eax
mov cx, 256
Xinit_fractal2:
mov ds:[di], eax
add di, 4
dec cx
jnz Xinit_fractal2
xor di, di
mov cx, 4000h
rep stosd
ret
; switch to gfx-mode
; used registers: all ?
Xinit_gfx:
mov ax, 0013h
int 10h
mov si, offset Xvga ; rewrite some vga-regisers
Xinit_gfx2:
lodsw
cmp ax, -1 ; is it all done ?
je Xinit_gfx3
mov dx, ax
Xinit_gfx1:
lodsw
cmp ax, -1 ; use next port ?
je Xinit_gfx2
out dx, ax
jmp Xinit_gfx1
Xinit_gfx3:
mov dx, 03c2h ; screen height: 100 -> 120
mov al, 0e3h
out dx, al
mov dx, 03c8h
xor al, al
out dx, al
inc dx
mov cx, 00h
Xinit_gfx4:
mov al, cl
shr al, 1h
out dx, al
out dx, al
out dx, al
inc cx
cmp cx, 080h
jne Xinit_gfx4
mov cx, 180h
xor al, al
Xinit_gfx5:
out dx, al
dec cx
jnz Xinit_gfx5
jne Xinit_gfx4
ret
; Xinitialize the sin-lookup-table
; used registers: all ?
Xinit_sin:
xor ax, ax
mov cx, Xsin_values+1
xor di, di
Xinit_sin1:
push ax
push cx
push di
call Xsin
mov ds:Xsins[di], ax
mov ds:Xsins3[di], ax
neg di
mov ds:Xsins2[di], ax
neg ax
mov ds:Xsins3[di], ax
neg di
mov ds:Xsins2[di], ax
pop di
pop cx
pop ax
inc ax
inc di
inc di
dec cx
jnz Xinit_sin1
xor ebx, ebx
ret
; check if a key was pressed
; used registers: ax
Xkey_pressed:
mov ah, 01h
int 16h
ret
Xmain:
call Xinit
Xmain_loop:
cmp Xtimer, 1400
jz Xmain_end
call Xproceed
call Xbuild
call Xdump
call Xkey_pressed
jz Xmain_loop
mov ah, 00h
int 16h
Xmain_end:
call Xclean_up
mov ax, 4c00h
int 21h
; create the mul-lookup-table
; used registers: all ?
Xinit_fastmul:
push es
mov ax, seg _fastmul
mov es, ax
xor ebx, ebx
Xinit_fastmul1:
mov al, bh
imul bl
sar ax, 7
mov es:[bx], al
inc bx
jnz Xinit_fastmul1
pop es
ret
; move the sun-source
; used registers: all ?
Xproceed:
add Xtimer, 1
mov bx, Xtimer ; move the light-source
add bx, 6000
and bx, (8*Xsin_values)-2
mov ax, Xsins[bx]
sar ax, 8
neg al
mov Xsun_y, al
mov cx, Xcoss[bx]
mov bx, Xtimer
shl bx, 2
add bx, Xtimer
add bx, 588h
and bx, (4*Xsin_values)-1
add bx, bx
mov ax, Xsins[bx]
imul cx
sar dx, 8
or dl, dl
jns Xproceed1
neg dl
Xproceed1:
mov Xsun_x, dl
mov ax, Xcoss[bx]
imul cx
sar dx, 8
mov Xsun_z, dl
mov ax, Xtimer ; rotate the world
add ax, ax
add ax, 120h
mov bx, ax
and bx, 8*Xsin_values-2
mov ax, Xsins[bx]
add ah, 80h
shr ax, 6
add ax, ax
mov bx, ax
shr ax, Xsin_base
and ax, 3
mov Xphase, ax
and bx, (Xsin_values)-1
add bx, Xsin_values/2
add bx, bx
mov cx, 4
mov si, offset Xpoint0
mov di, offset Xx0
Xproceed2:
mov ax, ds:[si] ; new x-coordinate
imul Xcoss[bx]
mov bp, dx
mov ax, ds:[si+2]
imul Xsins[bx]
sub bp, dx
add bp, bp
mov ds:[di], bp
mov ax, ds:[si] ; new y-coordinate
imul Xsins[bx]
mov bp, dx
mov ax, ds:[si+2]
imul Xcoss[bx]
add bp, dx
sar bp, 1
mov ds:[di+8], bp
add si, 4
add di, 2
dec cx
jnz Xproceed2
test Xtimer, 1
je Xproceed3
mov di, offset Xhght1
call Xmake_fractal
mov bx, Xtimer
shl bx, 9
mov di, offset Xhght1
call Xget_normals
jmp Xproceed4
Xproceed3:
mov di, offset Xhght2
call Xmake_fractal
mov bx, Xtimer
shl bx, 9
mov di, offset Xhght2
call Xget_normals
Xproceed4:
cmp Xtimer,1
jne Xproceed5
mov cx, 80h
xor eax, eax
mov di, 200h
rep stosd
Xproceed5:
add Xoffset, 200h
ret
; pseudo random number generator
; used registers: ax, dx
Xrand:
mov ax, 1549h
mul Xsrand
xor ax, 4286h
mov Xsrand, ax
ret
; create landscape "sink"
; used registers: eax, ebx, ecx, edx, edi
Xsink:
xor di, di
mov cx, 0080h
Xsink1:
mov bx, 0080h
Xsink2:
mov al, 40h
sub al, bl
imul al
mov dx, ax
mov al, 40h
sub al, cl
imul al
add ax, dx
shl eax, 16
push bx
push cx
push di
call Xsqrt
pop di
pop cx
pop bx
mul ax
shl dx, 1
sub dx, 2800h
mov es:[di], dx
add di, 4
dec bx
jnz Xsink2
dec cx
jnz Xsink1
ret
; calculate the a sin-value ax -> ax
; used registers: all ?
Xsin:
mov ebx, 3373259426 ; <-- 2**30 * pi
movzx eax, ax ; calculate x
mul ebx
shrd eax, edx, Xsin_base+1
mov esi, eax ; iteratively calculate the summands
mov ebp, eax ; +x
mov ebx, 6/2 ; -x^3 / 3!
call Xtaylor
sub ebp, eax
mov bl, 20/2 ; +x^5 / 5!
call Xtaylor
add ebp, eax
mov bl, 42/2 ; -x^7 / 7!
call Xtaylor
sub ebp, eax
mov bl, 72/2 ; +x^9 / 9!
call Xtaylor
add ebp, eax
mov bl, 110/2 ; -x^11 / 11!
call Xtaylor
sub ebp, eax
mov bl, 156/2 ; +x^13 / 13!
call Xtaylor
add ebp, eax
mov bl, 210/2/2 ; -x^15 / 15! , avoid 0x40000000
call Xtaylor
sub ebp, eax
shr ebp, 15
mov eax, ebp
ret
; calculate the square-root: eax -> eax
; used registers: eax, ebx, ecx, edx, edi
Xsqrt:
mov edx, eax
mov ebx, 80000000h
Xsqrt_1:
rol ebx, 1
shr edx, 2
jnz Xsqrt_1
xor edi, edi
mov ecx, eax
Xsqrt_2:
or ebx, ebx
jz Xsqrt_4
add edi, ebx
mov eax, edi
mul edi
cmp ecx, eax
ja Xsqrt_3
sub edi, ebx
Xsqrt_3:
shr ebx, 1
jmp Xsqrt_2
Xsqrt_4:
mov eax, edi
ret
; auxiliary routine to get the next summand in the Xtaylor-series of sin
; used registers: ?
Xtaylor:
mul esi
shrd eax, edx, 30
mul esi
shrd eax, edx, 31
xor edx, edx
div ebx
ret
_sun ends
end Xmain