Files
Work/ddraw/HOLD/TRIMAP32.ASM
2024-08-07 09:16:27 -04:00

437 lines
26 KiB
NASM

;********************************************************************************************************
; MODULE: TRIMAP32.ASM DATE: FEBRUARY 11, 1999
; AUTHOR: SEAN M. KESSLER
; TARGET: 32 BIT TARGET
; FUNCTION : TEXTURE MAPPING TRIANGLES
;********************************************************************************************************
SMART
.386
.MODEL FLAT
.DATA
BitShift EQU 0Bh
bmData@@mSrcWidth DD ?
bmData@@mSrcHeight DD ?
bmData@@mSrcExtent DD ?
bmData@@mlpSrcPtr DD ?
bmData@@mDstWidth DD ?
bmData@@mDstPitch DD ?
bmData@@mDstHeight DD ?
bmData@@mDstExtent DD ?
bmData@@mlpDstPtr DD ?
bmData@@mlpDstIndexPtr DD ?
bmData@@mlpPixelCallback DD ?
bmData@@mlpEdgeCallback DD ?
.LALL
INCLUDE ..\COMMON\COMMON.INC
INCLUDE ..\DDRAW\TRIMAP32.INC
INCLUDE ..\DDRAW\UTIL32.INC
.CODE
edgeCallback MACRO
pushad ; save all general purpose registers
push esi ; save pointer to edge
call bmData@@mlpEdgeCallback ; call handler
add esp,04h ; adjust stack
popad ; restore all general purpose registers
ENDM
pixelCallback MACRO
pushad ; save all general purpose registers
mov eax,ui ; move ui to eax register
round eax ; adjust/round
push eax ; save ui
mov eax,vi ; move vi to eax register
round eax ; adjust/round
push eax ; save vi
push x ; save x
push y ; save y
call bmData@@mlpPixelCallback ; call callback
add esp,10h ; adjust stack
popad ; restore all general purpose registers
ENDM
pixelMarker MACRO
pushad ; save all general purpose registers
push 0000h ; push 0
push 0000h ; push 0
push 0000h ; push 0
push 0000h ; push 0
call bmData@@mlpPixelCallback ; call callback
add esp,10h ; adjust stack
popad ; restore all general purpose registers
ENDM
round MACRO register
LOCAL @@return
mov edx,register ; copy register to edx
and edx,7FFh ; get remainder to edx register
shr register,BitShift ; get whole number to register
cmp edx,400h ; if remainder>1024 then increment eax
jle @@return ; ... otherwise return
inc register ; increment value in eax
@@return:
ENDM
scanline MACRO
mov ecx,[esi].DirectTriEdge@@mxRight ; move mxRight into ecx
sub ecx,[esi].DirectTriEdge@@mxLeft ; subtract out mxLeft, this is dx
cmp ecx,0000h ; compare dx to zero
je @@scanlineLoopEnd ; if dx is zero then don't scan the line
; mov eax,[esi].DirectTriEdge@@muRight ; move muRight into eax
; sub eax,[esi].DirectTriEdge@@muLeft ; subtract out muLeft
mov eax,[esi].DirectTriEdge@@muLeft ; move muLeft into eax register
sub eax,[esi].DirectTriEdge@@muRight ; subtract out muRight
shl eax,BitShift ; multiply this by 2048
divide eax,ecx ; divide by dx, this is du
mov du,eax ; store du into local variable
; mov eax,[esi].DirectTriEdge@@mvRight ; move mvRight into eax
; sub eax,[esi].DirectTriEdge@@mvLeft ; subtract out mvLeft
mov eax,[esi].DirectTriEdge@@mvLeft ; move mvLeft into eax
sub eax,[esi].DirectTriEdge@@mvRight ; subtract out mvRight
shl eax,BitShift ; multiply this by 2048
divide eax,ecx ; divide by dx, this is dv
mov dv,eax ; store dv into local variable
mov eax,[esi].DirectTriEdge@@muLeft ; move muLeft into eax
mov ui,eax ; muLeft is initial value for ui
mov eax,[esi].DirectTriEdge@@mvLeft ; move mvLeft into eax
mov vi,eax ; mvLeft is initial value for vi
mov eax,[esi].DirectTriEdge@@mxLeft ; move mxLeft into eax
mov x,eax ; mxLeft is initial value for x
shr x,BitShift ; truncate mxLeft value
pixelMarker
@@scanlineLoop: ; scanline loop sync address
mov eax,[esi].DirectTriEdge@@mxRight ; move mxRight into eax
shr eax,BitShift ; truncate mxRight
cmp x,eax ; compare x to mxRight
jg @@scanlineLoopEnd ; if x>mxRight then we're done with the scanline
pixelCallback
getSrcDataByte ; get source byte at [ui][vi] to cl register
setDstDataByte ; set destination byte at [x][y],cl
incrementScanLine ; advance along the scanline
jmp @@scanlineLoop ; continue execution
@@scanlineLoopEnd: ; end scanline sync address
ENDM
incrementScanLine MACRO ; advance along the scanline
mov eax,ui ; move ui to eax
shl eax,BitShift ; multiply by 2048
add eax,du ; add in du
shr eax,BitShift ; divide by 2048
mov ui,eax ; update ui
mov eax,vi ; move vi to eax
shl eax,BitShift ; multiply by 2048
add eax,dv ; add in dv
shr eax,BitShift ; divide by 2048
mov vi,eax ; update vi
inc x ; increment x
ENDM
getSrcDataByte MACRO ; cl=getSrcDataByte(ui,vi)
LOCAL @@continue
mov ebx,vi ; move column into ebx
round ebx ; round the result
cmp ebx,bmData@@mSrcWidth ; compare column to width
jge @@continue ; if column greater than width we're done
mov eax,ui ; move row into eax
round eax ; round the result
cmp eax,bmData@@mSrcHeight ; compare row to height
jge @@continue ; if row greater than height we're done
imul eax,bmData@@mSrcWidth ; multiply (row*width)->eax
add eax,bmData@@mSrcWidth ; add in the width
mov edx,bmData@@mSrcExtent ; move bitmap extent to edx
sub edx,eax ; subtract (row*width)+width from extent
add edx,ebx ; now add in the column
mov ebx,bmData@@mlpSrcPtr ; move bitmap pointer into ebx
mov cl,byte ptr[ebx+edx] ; get the byte
@@continue:
ENDM
setDstDataByte MACRO ; setDstDataByte x,y,cl
mov eax,x ; move column into ebx
cmp eax,bmData@@mDstWidth ; compare column to width
jge @@continue ; if column greater than width, return
mov eax,y ; move row into eax
cmp eax,bmData@@mDstHeight ; compare row to height
jge @@continue ; if row greater than height, return
imul eax,bmData@@mDstWidth ; multiply (row*width)->eax
add eax,bmData@@mDstWidth ; add in the width
mov edx,bmData@@mDstExtent ; move bitmap extent to edx
sub edx,eax ; subtract (row*width)+width from extent
add edx,x ; now add in the column
mov eax,bmData@@mlpDstPtr ; move bitmap pointer into ebx
mov byte ptr[eax+edx],cl ; set the byte
@@continue:
ENDM
verifyLeft MACRO ; verifyLeft(eax has mxLeft)
LOCAL @@noChangeDir ; local sync address
cmp scanMode,0002h ; check the scan mode
jne @@noChangeDir ; if scan mode is not LeftHandDiscontinuous then done
mov ebx,[esi].DirectTriEdge@@mx2 ; move x2 into ebx register
shl ebx,BitShift ; adjust ebx for precision
cmp eax,ebx ; compare mxLeft to x2
jge @@noChangeDir ; if mxLeft>=x1 then we're okay
sub eax,[esi].DirectTriEdge@@mDXLeft ; subtract out mDXLeft, this is adjusted mxLeft
mov [esi].DirectTriEdge@@mxLeft,eax ; save adjusted mxLeft
mov ebx,[esi].DirectTriEdge@@my1 ; move y1 into ebx register
sub ebx,y ; subtract (y1-y)
mov ecx,[esi].DirectTriEdge@@mx1 ; move x1 into ecx register
sub ecx,[esi].DirectTriEdge@@mx2 ; subtract (x1-x2)
shl ecx,BitShift ; adjust eax for precision
divide ecx,ebx ; eax has (x1-x2)/(y1-y), result to eax
mov [esi].DirectTriEdge@@mDXLeft,eax ; this is new mDXLeft
mov ebx,[esi].DirectTriEdge@@mxLeft ; move mxLeft into ebx register
add ebx,eax ; ebx has mxLeft+mDXLeft
mov [esi].DirectTriEdge@@mxLeft,ebx ; this is new mxLeft
@@noChangeDir: ; no change direction sync address
ENDM
verifyRight MACRO ; verifyRight (eax has mxRight)
LOCAL @@noChangeDir ; local sync address
cmp scanMode,0001h ; check the scan mode
jne @@noChangeDir ; if scan mode is not RightHandDiscontinuous then done
mov ebx,[esi].DirectTriEdge@@mx2 ; is mxRight greater than x2
shl ebx,BitShift ; adjust ebx for precision
cmp eax,ebx ; check mxLeft against x2
jle @@noChangeDir ; if mxLeft<=x2 then we're okay
sub eax,[esi].DirectTriEdge@@mDXRight ; subtract mDXRight from mxRight
mov [esi].DirectTriEdge@@mxRight,eax ; this is new mxRight
mov ebx,[esi].DirectTriEdge@@my1 ; move y1 into ebx register
sub ebx,[esi].DirectTriEdge@@my2 ; subtract (y1-y2) this is new dy
mov ecx,[esi].DirectTriEdge@@mx1 ; move x1 into ecx
sub ecx,[esi].DirectTriEdge@@mx2 ; subtract (x1-x2)
shl ecx,BitShift ; muliply by 2048 for precision
divide ecx,ebx ; ecx has (x1-x2)/(y1-y), result to eax
mov [esi].DirectTriEdge@@mDXRight,eax ; this is new mDXRight
mov ebx,[esi].DirectTriEdge@@mxRight ; move mxRight into ebx register
add ebx,eax ; add mDXRight to mxRight
mov [esi].DirectTriEdge@@mxRight,ebx ; this is new mxRight
@@noChangeDir:
ENDM
increment MACRO
mov eax,[esi].DirectTriEdge@@mxLeft ; move mxLeft into eax
add eax,[esi].DirectTriEdge@@mDXLeft ; add in the delta
mov [esi].DirectTriEdge@@mxLeft,eax ; this is new mxLeft
verifyLeft ; verify mxLeft
mov eax,[esi].DirectTriEdge@@mxRight ; move mxRight into eax
add eax,[esi].DirectTriEdge@@mDXRight ; add in the delta
mov [esi].DirectTriEdge@@mxRight,eax ; this is new mxRight
verifyRight ; verify mxLeft
mov eax,[esi].DirectTriEdge@@muLeft ; move muLeft into eax
add eax,[esi].DirectTriEdge@@mDULeft ; add in the delta
mov [esi].DirectTriEdge@@muLeft,eax ; this is new muLeft
mov eax,[esi].DirectTriEdge@@muRight ; move muRight into eax
add eax,[esi].DirectTriEdge@@mDURight ; add in the delta
mov [esi].DirectTriEdge@@muRight,eax ; this is new muRight
mov eax,[esi].DirectTriEdge@@mvLeft ; move mvLeft into eax
add eax,[esi].DirectTriEdge@@mDVLeft ; add in the delta
mov [esi].DirectTriEdge@@mvLeft,eax ; this is new mvLeft
mov eax,[esi].DirectTriEdge@@mvRight ; move mvRight into eax
add eax,[esi].DirectTriEdge@@mDVRight ; add in the delta
mov [esi].DirectTriEdge@@mvRight,eax ; this is new mvRight
inc y ; increment y
ENDM
initialize MACRO
LOCAL @@RightHandDiscontinuous,@@LeftHandleDiscontinuous,@@LevelPlane,@@NonLevelPlane,@@PlaneInitSync, \
@@InitFailed
mov eax,[esi].DirectTriEdge@@my2 ; move y2 into eax register
cmp eax,[esi].DirectTriEdge@@my0 ; does y2==y0
je @@LevelPlane ; if so then handle initialization for it
mov eax,[esi].DirectTriEdge@@mx2 ; move x2 into eax register
cmp eax,[esi].DirectTriEdge@@mx1 ; compare x2 to x1
jg @@RightHandDiscontinuous ; if x2>x1 then it's right handed
jmp @@LeftHandDiscontinuous ; otherwise we treat it as left handed
@@LevelPlane: ; LevelPlane sync address
mov scanMode,0000h ; set mode for traversal
mov ebx,[esi].DirectTriEdge@@my1 ; move y1 into ebx register
sub ebx,[esi].DirectTriEdge@@my2 ; ebx has (y1-y2), this is dy
cmp ebx,0000h ; is ebx zero?
je @@InitFail ; if so then set error code
mov eax,[esi].DirectTriEdge@@mx1 ; move x1 into eax
sub eax,[esi].DirectTriEdge@@mx0 ; eax has (x1-x0)
shl eax,BitShift ; multiply result by 2048 for precision
divide eax,ebx ; eax has (x2-x0)/(y1-y2)
mov [esi].DirectTriEdge@@mDXLeft,eax ; this is mDXLeft
mov eax,[esi].DirectTriEdge@@mx1 ; move x1 into eax register
sub eax,[esi].DirectTriEdge@@mx2 ; eax has (x1-x2)
shl eax,BitShift ; multiply result by 2048 for precision
divide eax,ebx ; eax has (x1-x2)/(y1-y2)
mov [esi].DirectTriEdge@@mDXRight,eax ; this is mDXRight
mov eax,[esi].DirectTriEdge@@mx0 ; move x0 into eax register
mov ebx,[esi].DirectTriEdge@@mx2 ; move x2 into ebx register
shl eax,BitShift ; adjust mxLeft for precision
shl ebx,BitShift ; adjust mxRight for precision
mov [esi].DirectTriEdge@@mxLeft,eax ; mxLeft=x0
mov [esi].DirectTriEdge@@mxRight,ebx ; mxRight=x2
jmp @@PlaneInitSync ; we're done initializing x,y params
@@RightHandDiscontinuous: ; RightHandDiscontinuous sync address
mov scanMode,0001h ; set mode for traversal
mov ebx,[esi].DirectTriEdge@@my1 ; move y1 to ebx register
sub ebx,[esi].DirectTriEdge@@my0 ; ebx has (y1-y0), this is dy
mov eax,[esi].DirectTriEdge@@mx1 ; move x1 to eax register
sub eax,[esi].DirectTriEdge@@mx0 ; eax has (x1-x0)
shl eax,BitShift ; multiply result by 2048 for precision
divide eax,ebx ; eax has (x1-x0)/(y1-y0)
mov [esi].DirectTriEdge@@mDXLeft,eax ; this is mDXLeft
mov ebx,[esi].DirectTriEdge@@my2 ; move y2 into ebx register
sub ebx,[esi].DirectTriEdge@@my0 ; ebx has (y2-y0), this is dy
mov eax,[esi].DirectTriEdge@@mx2 ; move x2 into eax register
sub eax,[esi].DirectTriEdge@@mx0 ; eax has (x2-x0)
shl eax,BitShift ; multiply eax by 2048 for precision
divide eax,ebx ; eax has (x2-x0)/(y2-y0)
mov [esi].DirectTriEdge@@mDXRight,eax ; this is mDXRight
mov eax,[esi].DirectTriEdge@@mx0 ; move x0 into eax register
shl eax,BitShift ; adjust mxLeft/mxRight for precision
mov [esi].DirectTriEdge@@mxLeft,eax ; move x0 into mxLeft
mov [esi].DirectTriEdge@@mxRight,eax ; move x0 into mxRight
jmp @@PlaneInitSync ; we're done initializing x,y params
@@LeftHandDiscontinuous: ; LeftHandDiscontinuous sync address
mov scanMode,0002h ; set mode for traversal
mov ebx,[esi].DirectTriEdge@@my2 ; move y2 into ebx register
sub ebx,[esi].DirectTriEdge@@my0 ; subtract (y2-y0), this is dy
mov eax,[esi].DirectTriEdge@@mx2 ; move x2 into eax register
sub eax,[esi].DirectTriEdge@@mx0 ; subtract x2-x0
shl eax,BitShift ; multiply by 2048 for precision
divide eax,ebx ; eax has (x2-x0)/(y2-y0)
mov [esi].DirectTriEdge@@mDXLeft,eax ; this is mDXLeft
mov ebx,[esi].DirectTriEdge@@my1 ; move y1 into ebx register
sub ebx,[esi].DirectTriEdge@@my0 ; subtract (y1-y0), this is dy
mov eax,[esi].DirectTriEdge@@mx1 ; move x1 into eax register
sub eax,[esi].DirectTriEdge@@mx0 ; subtract (x0-x1)
shl eax,BitShift ; multiply by 2048 for precision
divide eax,ebx ; divide (x1-x0)/(y1-y0)
mov [esi].DirectTriEdge@@mDXRight,eax ; this is mDXRight
mov eax,[esi].DirectTriEdge@@mx0 ; move x0 into eax register
shl eax,BitShift ; adjust mxLeft/mxRight for precision
mov [esi].DirectTriEdge@@mxLeft,eax ; mxLeft=x0
mov [esi].DirectTriEdge@@mxRight,eax ; mxRight=x0
jmp @@PlaneInitSync ; we're done initializing x,y params
@@PlaneInitSync: ; PlaneInitSync address
mov eax,[esi].DirectTriEdge@@mu2 ; move u2 into eax
sub eax,[esi].DirectTriEdge@@mu0 ; eax has (u2-u0)
shl eax,BitShift ; multiply result by 2048 for precision
divide eax,ebx ; eax has (u2-u0)/(y2-y0)
mov [esi].DirectTriEdge@@mDULeft,eax ; this is mDULeft
mov eax,[esi].DirectTriEdge@@mu1 ; move u1 into eax
sub eax,[esi].DirectTriEdge@@mu0 ; eax has (u1-u0)
shl eax,BitShift ; multiply result by 2048 for precision
divide eax,ebx ; eax has (u1-u0)/(y2-y0)
mov [esi].DirectTriEdge@@mDURight,eax ; this is mDURight
mov eax,[esi].DirectTriEdge@@mv2 ; move v2 into eax
sub eax,[esi].DirectTriEdge@@mv0 ; eax has (v2-v0)
shl eax,BitShift ; multiply result by 2048 for precision
divide eax,ebx ; eax has (v2-v0)/(y2-y0)
mov [esi].DirectTriEdge@@mDVLeft,eax ; this is mDVLeft
mov eax,[esi].DirectTriEdge@@mv1 ; move v1 into eax
sub eax,[esi].DirectTriEdge@@mv0 ; eax has (v1-v0)
shl eax,BitShift ; multiply result by 2048 for precision
divide eax,ebx ; eax has (v1-v0)/(y2-y0)
mov [esi].DirectTriEdge@@mDVRight,eax ; this is mDVRight
mov eax,[esi].DirectTriEdge@@mu0 ; move u0 into eax
mov [esi].DirectTriEdge@@muLeft,eax ; muLeft=u0
mov [esi].DirectTriEdge@@muRight,eax ; muRight=u0
mov eax,[esi].DirectTriEdge@@mv0 ; move v0 into eax
mov [esi].DirectTriEdge@@mvLeft,eax ; mvLeft=v0
mov [esi].DirectTriEdge@@mvRight,eax ; mvRight=v0
jmp @@InitSuccess ; jump over failure code
@@InitFail: ; InitFail sync address
stc ; Carry Flag set on failure
@@InitSuccess: ; InitSuccess sync address
ENDM
_directTriSetSrcBitmapInfo proc near ; void setSrcBitmapInfo(WORD width,WORD height,UHUGE *lpBitmapImage)
push ebp ; save old stack frame
mov ebp,esp ; create new stack frame
push eax ; save eax register
push ebx ; save ebx register
mov eax,dword ptr[ebp+08h] ; move width into eax register
mov bmData@@mSrcWidth,eax ; move width into bmData@@mSrcWidth
mov ebx,dword ptr[ebp+0Ch] ; move height into ebx register
mov bmData@@mSrcHeight,ebx ; move height into ebx register
imul eax,ebx ; multiply width*height, result to eax
mov bmData@@mSrcExtent,eax ; (width*height) to mSrcExtent
push dword ptr[ebp+10h] ; save lpBitmapImage on stack
pop bmData@@mlpSrcPtr ; restore in mlpSrcPtr
pop ebx ; restore ebx register
pop eax ; restore eax register
pop ebp ; restore old stack frame
retn ; return near to caller
_directTriSetSrcBitmapInfo endp
_directTriSetDstBitmapInfo proc near ; void setDstBitmapInfo(WORD width,WORD height,WORD pitch,UHUGE *lpBitmapImage)
push ebp ; save old stack frame
mov ebp,esp ; create new stack frame
push eax ; save eax register
push ebx ; save ebx register
mov eax,dword ptr[ebp+10h] ; move pitch into eax register
mov bmData@@mDstPitch,eax ; move pitch into mDstPitch
mov eax,dword ptr[ebp+08h] ; move width into eeax register
mov bmData@@mDstWidth,eax ; move width into mDstWidth
mov ebx,dword ptr[ebp+0Ch] ; move height into ebx register
mov bmData@@mDstHeight,ebx ; move height into mDstHeight
imul eax,ebx ; multiply width*height, result to eax
mov bmData@@mDstExtent,eax ; move (width*height) into mDstExtent
push dword ptr[ebp+14h] ; save lpBitmapImage on stack
pop bmData@@mlpDstPtr ; restore in mlpDstPtr
pop ebx ; restore ebx register
pop eax ; restore eax register
pop ebp ; restore old stack frame
retn ; return near to caller
_directTriSetDstBitmapInfo endp
_directTriSetPixelCallback proc near
push ebp
mov ebp,esp
mov eax,[ebp+08h]
mov bmData@@mlpPixelCallback,eax
pop ebp
retn
_directTriSetPixelCallback endp
_directTriSetEdgeCallback proc near
push ebp
mov ebp,esp
mov eax,[ebp+08h]
mov bmData@@mlpEdgeCallback,eax
pop ebp
retn
_directTriSetEdgeCallback endp
_directTriMapTexture proc near ; void directTriMapTexture(DirectTriEdge *pEdge)
LOCAL y:DWORD,x:DWORD,du:DWORD,dv:DWORD,ui:DWORD,vi:DWORD,scanMode:DWORD=LocalLength ; local variables for proc
push ebp ; save prior stack frame
mov ebp,esp ; create new frame
sub esp,LocalLength ; make room for local variables
pushad ; save all general purpose registers
mov esi,[ebp+08h] ; move pEdge to esi register
clc ; clear the carry flag
initialize ; initialize the edge
jc @@verticalLoopEnd ; if we failed to initialize edge then return
mov eax,[esi].DirectTriEdge@@my0 ; move y0 into eax
mov y,eax ; initialize y with y0
@@verticalLoop: ; beginning of vertical loop
mov ecx,[esi].DirectTriEdge@@my1 ; move y1 into ecx
cmp y,ecx ; compare y to y1
jg @@verticalLoopEnd ; if y>y1 then we're done
scanline ; perform scanline on the horizontal
increment ; increment along the vertical
edgeCallback ; call the edge handler
jmp @@verticalLoop ; continue execution
@@verticalLoopEnd: ; end loop sync address
popad ; restore all general purpose registers
add esp,LocalLength ; remove local variables from frame
pop ebp ; restore prior stack frame
retn ; return near to caller
_directTriMapTexture endp
public _directTriSetSrcBitmapInfo
public _directTriSetDstBitmapInfo
public _directTriMapTexture
public _directTriSetPixelCallback
public _directTriSetEdgeCallback
END