home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Party 1994: Try This At Home
/
disk_image.bin
/
source
/
gallery
/
a_proj.asm
< prev
next >
Wrap
Assembly Source File
|
1993-07-20
|
10KB
|
421 lines
; A_PROJ.ASM -- Projection, fog, and so on.
IDEAL
MODEL Compact, Pascal
RADIX 16
P286
INCLUDE "globals.inc"
DATASEG
EXTRN SkyTexture : DWord
EXTRN FloorTexture : DWord
PUBLIC ScrHeight
PUBLIC FogDensity
; saturation/darkness table (32 entries)
RADIX 10
SkyColor db 01ch
FloorColor db 078h
SatTable: ;0 6 10 13 16 18 20 22 2425 26 27 28 29 30 31
db 0,0,0,0,0,0,1,1,1,1,2,2,2,3,3,3,4,4,5,5,6,6,7,7,8,9,10,11,12,13,14,15
FogDensity db 6d
db ?
RADIX 16
; projection vars
factor1 dd ?
factor2 dd ?
factor3 dd ?
ObserDist dd ?
ScrHeight dw ?
EyeH dw ?
WallH dw ?
FARDATA FloorSky
EXTRN FloorSkyTable : Byte
CODESEG
EXTRN MapColumn : NEAR
EXTRN FilterColumn : NEAR
EXTRN FillColumn : NEAR
EXTRN RegisterRange : NEAR
EXTRN PlotFullScreen : NEAR;
PUBLIC InitProjection ;(Height,ObsDist,EyeHeight,WallHeight:Word)
; Calculates factor1,2,3. Must be called
; before Project.
; NOTE: call w/ EyeHeight>WallHeight & you die!
; (I think it's because I use unsigned mul & div...)
PUBLIC EyeHeight ;(EyeHeight:Word) Changes Eye Height much quicker
;than calling InitProjection
PUBLIC ReFloor ; updates floor & ceiling w/ EyeHeight & Fog Values
PUBLIC Project ;(Dest,Texture:Pointer;SideWall,Ofs,screenX,L:Word)
; Projects a column of texture (0..63)
; (Texture) onto ScreenColumns[Ofs]
; Height is height of screen (pixels)
; EyeHeight is height of observer
; L is distance to object
; Screen coords go from 0 to Height (top-bottom)
; H = Height of screen in Vpixels (centered at observer's eye)
; E = Height of Eye in Vpixels from floor
; W = Height of a Wall in Vpixels from floor
; L = Distance from Wall to Screen in Vpixels
; D = Distance from Observer to Screen in Vpixels
; projection:
; ─┬─
; │ Screen ─┬─
; Obs │ │
; *--------H-----------------------------│ Wall
; | D │ L │
; | │ │
; | ─┴─ │ W
; E | │
; | │
; | │
; | │
; ///////////////////////////////////////////////
;
; y(top) = H/2 - [ D*(W-E) ] / (L+D)
; = factor1 - factor2 div (L+D)
; y(bottom) = H/2 + [ D*E ] / (L+D)
; = factor1 + factor3 div (L+D)
PROC InitProjection NEAR
ARG H : Word, D : Word, E : Word, W : Word
P386
pushad
movzx eax, [H]
mov [ScrHeight], ax ; ScrHeight = H
shr eax,1
mov [factor1], eax ; factor1 = H/2
movzx eax, [W]
mov [WallH],ax
movzx ebx, [E]
mov [EyeH], bx
movzx ecx, [D]
mov [ObserDist], ecx ; ObserDist = D
sub eax, ebx
mul ecx
mov [factor2], eax ; factor2 = D(W-E)
movzx eax, [E]
mul ecx
mov [factor3], eax ; factor3 = D·E
popad
ret
P286
ENDP
; // EyeHeight
PROC EyeHeight NEAR
ARG E : Word
P386
USES eax, ebx, edx
mov ebx, [factor2] ; ebx = (DW-DE)'
add ebx, [factor3] ; ebx = (DW)'
movzx eax, [E] ; eax = E
mov [EyeH], ax
mul [ObserDist] ; eax = DE
mov [factor3], eax ; factor3 = DE
sub ebx, eax
mov [factor2], ebx ; factor2 = DW-DE
ret
P286
ENDP
; // Project
; remember:
; y(top) = H/2 - [ D*(W-E) ] / (L+D)
; = factor1 - factor2 div (L+D)
; y(bottom) = H/2 + [ D*E ] / (L+D)
; = factor1 + factor3 div (L+D)
PROC Project NEAR
ARG Dest : FAR PTR Byte, Texture : FAR PTR Byte, \
SideWall : Word, Ofs : Word, \
screenX : Word, L : Word
LOCAL Ytop : Word, Ybottom : Word, \
X0 : Word, X1 : Word, YbmYt : Word, Fog : Byte
P386
pushad
push es
mov ecx, [factor1]
movzx ebx, [L]
; shr ebx,3 ; scale length
add ebx, 8
; add ebx, [ObserDist] ; ebx = L+D
mov eax, [factor2]
xor edx, edx
div ebx
sub ecx, eax
mov [Ytop], cx
mov eax, [factor3]
xor edx, edx
div ebx
add eax, [factor1]
mov [Ybottom], ax
sub ax, cx
mov [YbmYt], ax ; Ybottom-Ytop
mov [X0], 0
mov [X1], TexRes-1
mov ax, [Ytop]
or ax, ax
jns @@SkipTopClip
; Ytop < 0, must clip top
movsx eax, [Ytop]
neg eax ; make positive
IF TexRes EQ 128d
shl eax, 7 ; *128
ENDIF
IF TexRes EQ 64d
shl eax, 6 ; *64
ENDIF
xor edx, edx
movzx ebx, [YbmYt]
div ebx
mov [X0], ax
mov [Ytop], 0
@@SkipTopClip:
mov ax, [Ybottom]
cmp ax, [ScrHeight]
jb @@SkipBotClip
; Ybottom > Height, must clip bottom
movzx eax, [Ybottom]
movzx ebx, [ScrHeight]
sub eax, ebx
IF TexRes EQ 128d
shl eax, 7 ; *128
ENDIF
IF TexRes EQ 64d
shl eax, 6 ; *64
ENDIF
movzx ebx, [YbmYt]
xor edx, edx
div ebx
mov bx, TexRes-1
sub bx, ax
mov [X1], bx
mov ax, [ScrHeight]
dec ax
mov [Ybottom], ax
@@SkipBotClip:
; Test for finale
mov al, [byte ptr SideWall]
cmp al, 10d ; final full-screen wall ?
jne @@notFinale
push [dword ptr Dest]
push [Ytop]
push [Ybottom]
push [Ofs]
push [screenX]
call PlotFullScreen
jmp @@continue
@@notFinale:
; calculate fog/darkness
mov ax, [L] ; get length
mov cl, [FogDensity] ; get fog/darkness density
shr ax, cl
; darken east-west walls
mov bl, [byte ptr SideWall+1]
test bl,1
jz @@notdarkside
add ax, 6
@@notdarkside:
cmp ax, 31d
jbe @@1
mov al, 31d
@@1:
mov bx, offset SatTable
xlat
mov [Fog], al
cmp al, 15d
jb @@wallVisible
push [dword ptr Dest]
push [Ytop] ; wall is completely black
push [Ybottom]
push [Ofs]
push 0 ; just draw a black column
call FillColumn
jmp @@continue
@@wallVisible:
push [dword ptr Texture]
push [dword ptr Dest]
push [X0]
push [X1]
push [Ytop]
push [Ybottom]
push [Ofs]
call MapColumn
cmp [Fog],0 ; skip filter if wall is too close
je @@continue ; for fog to have effect.
push [dword ptr Dest]
push [Ytop]
push [Ybottom]
push [Ofs]
push [word ptr Fog]
call FilterColumn
@@continue:
push [Ytop]
push [Ybottom]
call RegisterRange
pop es
popad
ret
P286
ENDP
; // ReFloor
PROC ReFloor NEAR
P386
USES eax, bx, cx, dx, si, di, es
mov ax, seg FloorSkyTable
mov es, ax
mov di, offset FloorSkyTable ; es:di -> Table
; SkyTexture
mov al, [FogDensity]
xor ah,ah
sub ax, 3
shl ax, 3 ; ax = 8*(FogDensity-3)
mov bx, [WallH]
sub bx, [EyeH]
shl bx, 6 ; bx = 64*(W-E)
add bx, ax
mov si, offset SkyTexture
mov al, [SkyColor]
mov ah,al
mov cx, ax
shl eax, 16d
mov ax, cx ; eax = ScScScSc
mov cx, 99d ; Y
@@SkyLoop:
cmp cl, [es:di+bx]
ja @@same1
sub eax,01010101h
inc bx
@@same1:
mov [si], eax
add si,4
loop @@SkyLoop
; FloorTexture
mov al, [FogDensity]
xor ah,ah
sub ax, 3
shl ax, 3 ; ax = 8*(FogDensity-3)
mov bx, [EyeH]
shl bx, 6 ; bx = 64*E
add bx, ax
mov si, offset FloorTexture
add si, 99d*4d
mov al, [FloorColor]
mov ah,al
mov cx, ax
shl eax, 16d
mov ax, cx ; eax = ScScScSc
mov cx, 99d ; Y
@@FloorLoop:
cmp cl, [es:di+bx]
ja @@same2
sub eax,01010101h
inc bx
@@same2:
mov [si], eax
sub si,4
loop @@FloorLoop
ret
P286
ENDP
END