;******************************************************************************************************** ; 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