home *** CD-ROM | disk | FTP | other *** search
- ; 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
-
-
-