;************************************************************************************* ; MODULE: TMAP32.ASM DATE: DECEMBER 28, 1994 ; AUTHOR: SEAN M. KESSLER JUNE 06, 1995 ; TARGET: 32 BIT TARGET ; FUNCTION : TEXTURE MAPPING POLYGONS IN PERSPECTIVE ;************************************************************************************* SMART .386 .MODEL FLAT .DATA .LALL INCLUDE ..\COMMON\COMMON.INC INCLUDE ..\ENGINE\TMAP32.INC ;bmData@@mGetCache Cache ? bmData@@mGetCache GetCache ? bmData@@mSrcWidth DW 00h bmData@@mSrcHeight DW 00h bmData@@mSrcExtent DD 00h bmData@@mlpSrcPtr DD 00h bmData@@mDstWidth DW 00h bmData@@mDstHeight DW 00h bmData@@mDstExtent DD 00h bmData@@mDstCacheRow DW 00h bmData@@mDstCacheMul DD 00h bmData@@mlpDstPtr DD 00h bmData@@mlpDstIndexPtr DD 00h bmData@@mPrecision DW 4000h bmData@@mMulCacheOne DW 00h bmData@@mMulCacheTwo DW 00h bmData@@mMulCacheVal DD 00h MINVALUE EQU -32767 MAXVALUE EQU 32767 MINVERTEX EQU 3 .CODE LOCALS isInGetCache MACRO cacheItem LOCAL @@return,@@okReturn,@@initCache,@@checkCachePlusOne, \ @@checkCachePlusTwo,@@checkCachePlusThree,@@checkCachePlusFour cmp bmData@@mGetCache.GetCache@@mCacheStatus,0FFh je @@initCache cmp cacheItem,bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mColRow jne @@checkCachePlusOne mov cl,bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mCacheData jmp @@okReturn @@checkCachePlusOne: cmp cacheItem,bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mColRow jne @@checkCachePlusTwo mov cl,bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mCacheData jmp @@okReturn @@checkCachePlusTwo: cmp cacheItem,bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mColRow jne @@checkCachePlusThree mov cl,bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mCacheData jmp @@okReturn @@checkCachePlusThree: cmp cacheItem,bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mColRow jne @@checkCachePlusFour mov cl,bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mCacheData jmp @@okReturn @@checkCachePlusFour: cmp cacheItem,bmData@@mGetCache.GetCache@@mCacheData[4].GetCacheData@@mColRow jne @@noGetCache mov cl,bmData@@mGetCache.GetCache@@mCacheData[4].GetCacheData@@mCacheData jmp @@okReturn @@initCache: mov bmData@@mGetCache.GetCache@@mCacheStatus,00h ; activate cache mechanism zeroCache @@noGetCache: stc jmp @@return @@okReturn: inc bmData@@mGetCache.GetCache@@mCacheHits clc @@return: ENDM zeroCache MACRO mov bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mColRow,0FFFFFFFFh mov bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mCacheData,0FFh mov bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mColRow,0FFFFFFFFh mov bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mCacheData,0FFh mov bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mColRow,0FFFFFFFFh mov bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mCacheData,0FFh mov bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mColRow,0FFFFFFFFh mov bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mCacheData,0FFh mov bmData@@mGetCache.GetCache@@mCacheData[4].GetCacheData@@mColRow,0FFFFFFFFh mov bmData@@mGetCache.GetCache@@mCacheData[4].GetCacheData@@mCacheData,0FFh ENDM rollCache MACRO mov edx,bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mColRow mov bl,bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mCacheData mov bmData@@mGetCache.GetCache@@mCacheData[4].GetCacheData@@mColRow,edx mov bmData@@mGetCache.GetCache@@mCacheData[4].GetCacheData@@mCacheData,bl mov edx,bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mColRow mov bl,bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mCacheData mov bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mColRow,edx mov bmData@@mGetCache.GetCache@@mCacheData[3].GetCacheData@@mCacheData,bl mov edx,bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mColRow mov bl,bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mCacheData mov bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mColRow,edx mov bmData@@mGetCache.GetCache@@mCacheData[2].GetCacheData@@mCacheData,bl mov edx,bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mColRow mov bl,bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mCacheData mov bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mColRow,edx mov bmData@@mGetCache.GetCache@@mCacheData[1].GetCacheData@@mCacheData,bl ENDM putCacheColRow MACRO cacheColRow mov bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mColRow,cacheColRow ENDM putCacheData MACRO cacheData mov bmData@@mGetCache.GetCache@@mCacheData[0].GetCacheData@@mCacheData,cacheData ENDM multiply MACRO varOne,varTwo LOCAL @@bypassCache,@@return movzx eax,varOne ; move varOne into eax register movzx edx,varTwo ; move varTwo into ebx register cmp ax,bmData@@mMulCacheOne ; check varOne against cache varOne jne @@bypassCache ; no match, we perform the multiply cmp dx,bmData@@mMulCacheTwo ; check varTwo against cache varTwo jne @@bypassCache ; no match, we perform the multiply mov eax,bmData@@mMulCacheVal ; cache hit, so use the cache value result jmp @@return ; we're done here @@bypassCache: ; bypass cache sync address mov bmData@@mMulCacheOne,ax ; store source into cache source mov bmData@@mMulCacheTwo,dx ; store destination imul eax,edx ; perform multiply, result to eax mov bmData@@mMulCacheVal,eax ; store result into cache result @@return: ; return sync address ENDM divide MACRO varOne,varTwo mov eax,varOne ; move varOne into eax register cdq ; convert doubleword in eax to quadword at edx:eax idiv varTwo ; divide eax/varTwo result to eax, remainder to edx ENDM roundEBX MACRO varOne LOCAL @@return mov edx,varOne ; move value into edx register mov ebx,varOne ; move value into ebx register and edx,00003FFFh ; get remainder into edx register shr ebx,14 ; get whole number to ebx register cmp edx,8192 ; if remainder > 8192, increment ebx jle @@return ; otherwise return inc ebx ; increment value in ebx @@return: ENDM roundEAX MACRO varOne LOCAL @@return mov edx,varOne ; move value into edx register mov eax,varOne ; move value into eax register and edx,00003FFFh ; get remainder into edx register shr eax,14 ; get whole number to eax register cmp edx,8192 ; if remainder > 8192, increment ebx jle @@return ; otherwise return inc eax ; increment value in eax @@return: ENDM getPoint MACRO address,index movzx eax,index ; move index into eax register shl eax,02h ; multiply ax by size of far pointer add eax,address ; add in the address movzx ebx,[eax].Point@@y ; get the y value to bx register movzx eax,[eax].Point@@x ; get the x value to ax register ENDM newEdge MACRO ; (PureEdge*) in eax, sets edx=1=error, otherwise edx=0 movzx ebx,[eax].PureEdge@@mEdgeDirection ; save edgeDirection push ebx ; push edgeDirection push [eax].PureEdge@@mCurrentEdgeEnd ; push currentEdge end (ie) nextEdge index mov ecx,eax ; move (PureEdge*) to ecx register call _setupEdge ; attempt to setup new edge add esp,06h ; readjust the stack mov edx,eax ; move return code to edx register ENDM getSrcDataByte MACRO ; BYTE getSrcDataByte(eax=colRow) LOCAL @@return,@@bypassCache,@@initCache ; local sync address labels isInGetCache eax jc @@bypassCache jmp @@return ; cmp bmData@@mGetCache.Cache@@mCacheStatus,0FFh ; is cache active yet ?? ; je @@initCache ; no, cache has not been intialized ; cmp eax,bmData@@mGetCache.Cache@@mColRow ; check colRow for cache hit ; jne @@bypassCache ; cache was not hit, so do the multiply ; mov cl,bmData@@mGetCache.Cache@@mCacheData ; yes, the cache was hit, use value ; jmp @@return ; now return clean. ;@@initCache: ; init cache sync address ; mov bmData@@mGetCache.Cache@@mCacheStatus,00h ; activate cache mechanism @@bypassCache: ; bypass cache sync address rollCache putCacheColRow ebx mov ebx,eax ; move colRow to ebx register ; mov bmData@@mGetCache.Cache@@mColRow,eax ; move colRow to cache colRow multiply bx,bmData@@mSrcWidth ; multiply (row*width)-> eax xor edx,edx ; clear edx mov dx,bmData@@mSrcWidth ; move width to edx register add eax,edx ; add in width (ie) (row*width)+width mov edx,bmData@@mSrcExtent ; move source bitmap extent to edx sub edx,eax ; sub result from source bmp extent shr ebx,10h ; ebx gets column add edx,ebx ; add column back in mov ebx,bmData@@mlpSrcPtr ; move mlpSrcPtr to ebx register mov cl,byte ptr[ebx+edx] ; get source byte at ebx+edx to cl ; mov bmData@@mGetCache.Cache@@mCacheData,cl ; save byte value to cache value putCacheData cl @@return: ; return sync address ENDM if 0 getSrcDataByte MACRO ; BYTE getSrcDataByte(eax=colRow) LOCAL @@return,@@bypassCache,@@initCache ; local sync address labels cmp bmData@@mGetCache.Cache@@mCacheStatus,0FFh ; is cache active yet ?? je @@initCache ; no, cache has not been intialized cmp eax,bmData@@mGetCache.Cache@@mColRow ; check colRow for cache hit jne @@bypassCache ; cache was not hit, so do the multiply mov cl,bmData@@mGetCache.Cache@@mCacheData ; yes, the cache was hit, use value jmp @@return ; now return clean. @@initCache: ; init cache sync address mov bmData@@mGetCache.Cache@@mCacheStatus,00h ; activate cache mechanism @@bypassCache: ; bypass cache sync address mov ebx,eax ; move colRow to ebx register mov bmData@@mGetCache.Cache@@mColRow,eax ; move colRow to cache colRow multiply bx,bmData@@mSrcWidth ; multiply (row*width)-> eax xor edx,edx ; clear edx mov dx,bmData@@mSrcWidth ; move width to edx register add eax,edx ; add in width (ie) (row*width)+width mov edx,bmData@@mSrcExtent ; move source bitmap extent to edx sub edx,eax ; sub result from source bmp extent shr ebx,10h ; ebx gets column add edx,ebx ; add column back in mov ebx,bmData@@mlpSrcPtr ; move mlpSrcPtr to ebx register mov cl,byte ptr[ebx+edx] ; get source byte at ebx+edx to cl mov bmData@@mGetCache.Cache@@mCacheData,cl ; save byte value to cache value @@return: ; return sync address ENDM endif setDstDataByte MACRO ; void setDstDataByte(cl=charByte) mov ebx,bmData@@mlpDstIndexPtr ; get scanline pointer to ebx mov byte ptr[ebx],cl ; move byte into frame bitmap inc bmData@@mlpDstIndexPtr ; increment scanline pointer ENDM setDstIndexPtr MACRO multiply [esi].PureMap@@myValue,bmData@@mDstWidth ; multiply row*width result to eax xor edx,edx ; clear edx register mov dx,bmData@@mDstWidth ; move width into dx register add eax,edx ; add (row*width)+width mov edx,bmData@@mDstExtent ; move (width*height) into ebx sub edx,eax ; calculate addValue-subValue mov bx,[esi].PureMap@@mxDest ; move column into bx register and ebx,0000FFFFh ; zero out high word of ebx add edx,ebx ; now add column number back in mov ebx,bmData@@mlpDstPtr ; move mlpDstPtr to ebx register add ebx,edx ; add offset to mlpDstPtr mov bmData@@mlpDstIndexPtr,ebx ; store offset to new index pointer ENDM increment MACRO ; assumes (PureEdge*) is in eax register, sets carry on error LOCAL @@newEdge,@@adjTerm,@@error,@@success,@@return dec [eax].PureEdge@@mRemainingScanLines ; decrement mRemainingScanLines jz @@newEdge ; if no more scan lines, try to setup new edge mov ebx,[eax].PureEdge@@mxSourceStep ; get mxSourceStep to ebx register add ebx,[eax].PureEdge@@mxSource ; add in mxSource mov [eax].PureEdge@@mxSource,ebx ; replace mxSource with new value mov ebx,[eax].PureEdge@@mySourceStep ; get mySourceStep into ebx register add ebx,[eax].PureEdge@@mySource ; add in mySource mov [eax].PureEdge@@mySource,ebx ; replace mySource with new value mov bx,[eax].PureEdge@@mxDestLocation ; get mxDestLocation into ebx register add bx,[eax].PureEdge@@mxStep ; add in mxStep mov [eax].PureEdge@@mxDestLocation,bx ; replace mxDestLocation with new value mov bx,[eax].PureEdge@@mxErrorTerm ; get mxErrorTerm to bx register add bx,[eax].PureEdge@@mxAdjustUp ; add in mxAdjustUp mov [eax].PureEdge@@mxErrorTerm,bx ; replace mxErrorTerm with new value cmp bx,00h ; compare mxErrorTerm to zero jle @@success ; mxErrorTerm is less equal zero @@adjTerm: ; adjTerm sync address mov bx,[eax].PureEdge@@mxDestLocation ; get mxDestLocation to bx register add bx,[eax].PureEdge@@mxDirection ; add in mxDirection mov [eax].PureEdge@@mxDestLocation,bx ; replace mxDestLocation with new value mov bx,[eax].PureEdge@@mxErrorTerm ; move mxErrorTerm into bx register sub bx,[eax].PureEdge@@mxAdjustDown ; add in mxAdjustDown mov [eax].PureEdge@@mxErrorTerm,bx ; replace mxErrorTerm with new value jmp @@success ; we're done here @@newEdge: ; newEdge sync address newEdge ; attempt to create new edge cmp edx,0001h ; did prior call fail ? jne @@success ; no, we're done here @@error: ; error sync address stc ; error sets carry jmp @@return ; jump to return @@success: ; ok sync address clc ; success clears carry @@return: ; return sync address ENDM scanOutputLine MACRO ; void scanOutputLine(ecx=(PureEdge*)) LOCAL @@xLoop,@@skipImageBit,@@continue,@@return ; local label mov edi,[esi].PureMap@@mlpLeftEdge ; move (PureEdge*)lpLeftEdge to ecx register mov eax,[edi].PureEdge@@mxSource ; move PureEdge::mxSource to eax register mov [esi].PureMap@@mxSource,eax ; move PureEdge::mxSource to PureMap::mxSource mov eax,[edi].PureEdge@@mySource ; move PureEdge::mySource to eax register mov [esi].PureMap@@mySource,eax ; move PureEdge::mySource to PureMap::mySource mov dx,[edi].PureEdge@@mxDestLocation ; move PureEdge::mxDestLocation to ax mov [esi].PureMap@@mxDest,dx ; move PureEdge::mxDestLocation to PureMap::mxDest mov edi,[esi].PureMap@@mlpRightEdge ; move (PureEdge*)lpRightEdge to ecx register xor eax,eax ; clear out eax register mov ax,[edi].PureEdge@@mxDestLocation ; move PureEdge::mxDestLocation to ax register mov [esi].PureMap@@mxDestMax,ax ; move PureEdge::mxDestLocation to PureMap::mxDestMax sub ax,dx ; mxDestMax-mxDest jz @@return ; if width is zero then return mov [esi].PureMap@@mDestWidth,eax ; move width into PureMap::mDestWidth mov eax,[edi].PureEdge@@mxSource ; move PureEdge::mxSource into eax sub eax,[esi].PureMap@@mxSource ; subtract out PureMap::mxSource divide eax,[esi].PureMap@@mDestWidth ; now divide by PureMap::mDestWidth mov [esi].PureMap@@mxSourceStep,eax ; move new value to PureMap@@mxSourceStep mov eax,[edi].PureEdge@@mySource ; move PureEdge::mySource into eax sub eax,[esi].PureMap@@mySource ; subtract out PureMap::mySource divide eax,[esi].PureMap@@mDestWidth ; now divide by PureMap::mDestWidth mov [esi].PureMap@@mySourceStep,eax ; move new value to PureMap@@mySourceStep mov bmData@@mlpDstIndexPtr,00h ; initialize scanline pointer @@xLoop: ; xLoop test mov ax,[esi].PureMap@@mxDest ; move mxDest to ax register cmp ax,[esi].PureMap@@mxDestMax ; compare mxDest to ax register jge @@return ; if its greater equal return cmp ax,bmData@@mDstWidth ; is destination x greater than frame width? jge @@return ; yes, stop scanning this output line or ax,ax ; does mxDest extend too far left of frame buffer jl @@skipImageBit ; if it does then skip putImageBits cmp bmData@@mlpDstIndexPtr,00h ; check the index pointer jne @@continue ; if it's not null we continue along setDstIndexPtr ; set destination index pointer to row/col @@continue: ; sync address roundEBX [esi].PureMap@@mySource ; convert and round PureMap@@mySource -> ebx roundEAX [esi].PureMap@@mxSource ; convert and round PureMap@@mxSource -> eax shl eax,16 ; move column into high word mov ax,bx ; move row into low word getSrcDataByte ; getSrcDataByte at eax=colRow, byteValue gets placed into cl setDstDataByte ; setDstDataByte at mlpDstIndexPtr,cl=byteValue @@skipImageBit: ; skipImageBit bypass address mov eax,[esi].PureMap@@mxSourceStep ; move mxSourceStep to eax add [esi].PureMap@@mxSource,eax ; add mxSouceStep to mxSource mov ebx,[esi].PureMap@@mySourceStep ; move mySourceStep to eax add [esi].PureMap@@mySource,ebx ; add mySourceStep to mySource inc [esi].PureMap@@mxDest ; increment loop counter jmp @@xLoop ; loop through xLoop @@return: ; return sync label ENDM _mapTexture proc near ; void mapTexture(PureMap *lpTextureMap) push ebp ; save old stack frame mov ebp,esp ; create new stack frame pushad ; save all general purpose registers, required. mov esi,dword ptr[ebp+8] ; move (PureMap*) to esi register mov edx,[esi].PureMap@@mlpLeftEdge ; move PureMap->mlpLeftEdge to edx mov bx,[edx].PureEdge@@mMaxVertex ; move left edge mMaxVertex to bx register getPoint [edx].PureEdge@@mlpDstList,bx ; get point mov [esi].PureMap@@myValue,bx ; myValue=mLeftEdge[mLeft.maxVertex()].y() @@forever: ; (ie) while(TRUE) mov ax,[esi].PureMap@@myValue ; move myValue to ax register cmp ax,bmData@@mDstHeight ; is myValue greater than frame buffer height jge @@return ; if so then we're done mapping the texture cmp ax,00h ; is myValue within frame buffer at all jl @@skipOutputLine ; if not then skip this output line scanOutputLine ; scan along the output line, (PureMap*) in ecx for macro @@skipOutputLine: ; skipOutputLine sync address mov eax,[esi].PureMap@@mlpLeftEdge ; move (PureEdge*) left edge to eax increment ; increment along left edge jc @@return ; if carry set, edge failed to increment, we're done mov eax,[esi].PureMap@@mlpRightEdge ; move (PureEdge*) right edge to eax increment ; increment along right edge jc @@return ; if carry set, edge failed to increment, we're done inc [esi].PureMap@@myValue ; increment y position jmp @@forever ; loop until all edges are completed @@return: ; return sync address popad ; restore all general purpose registers pop ebp ; restore old stack frame retn ; return near to caller _mapTexture endp _initEdge proc near ; void initEdge(long edgeType,PureEdge *lpEdge); push ebp ; save old stack frame mov ebp,esp ; create new stack frame push ebx ; save ebx register mov ecx,dword ptr[ebp+12] ; move edge ptr to ecx register call _getMinMaxInfo ; find minimum and maximum vertices cmp eax,0000h ; make sure previous call returned success jne @@return ; if not then return push dword ptr[ebp+8] ; push edge type (-1:leftEdge,1:rightEdge) push [ecx].PureEdge@@mStartVertex ; push startVertex call _setupEdge ; now setup the edge add esp,06h ; readjust the stack @@return: ; return label pop ebx ; restore ebx register pop ebp ; restore old stack frame retn ; return to caller _initEdge endp _setupEdge proc near ; long setupEge(long edgeType,int startVertex); LOCAL nextVertex:WORD,startVertex:WORD,xDestWidth:WORD,yDestHeight:DWORD=LocalLength push ebp ; save old stack frame mov ebp,esp ; create new stack frame sub esp,LocalLength ; make room for local variables mov bx,word ptr[ebp+10] ; move edge type to bx register mov [ecx].PureEdge@@mEdgeDirection,bx ; store edge direction in variable mov bx,word ptr[ebp+8] ; move startVertex to bx register mov [ecx].PureEdge@@mStartVertex,bx ; move startVertex into mStartVertex mov startVertex,bx ; move startVertex into startVertex @@forever: ; forever loop label mov bx,startVertex ; move startVertex to bx register cmp bx,[ecx].PureEdge@@mMinVertex ; is startVertex same as mMinVertex ? je @@error ; if so then we're all done here add bx,[ecx].PureEdge@@mEdgeDirection ; add edge direction to startVertex mov nextVertex,bx ; move result to nextVertex mov bx,[ecx].PureEdge@@mNumVertexes ; move number of vertexes to bx register cmp nextVertex,bx ; compare nextVertex to number of vertexes jge @@zervert ; next vertex is greater eq number of vertexes cmp nextVertex,00h ; compare nextVertex to zero jl @@adjvert ; nextVertex is less than zero jmp @@bypass ; jump over next conditonal @@zervert: ; handle nextVertex>=number of vertexes mov nextVertex,00h ; set nextVertex to zero jmp @@bypass ; jump over next conditional @@adjvert: ; handle nextVertex<0 dec bx ; decrement value count in bx register mov nextVertex,bx ; set nextVertex to (numVertex-1) @@bypass: ; bypass sync address getPoint [ecx].PureEdge@@mlpDstList,nextVertex ; get mlpDstList[nextVertex] push bx ; dstList[nextVertex].y() in bx, save it. getPoint [ecx].PureEdge@@mlpDstList,startVertex ; get mlpDstList[startVertex] pop ax ; restore first x point to ax sub ax,bx ; now subtract second x point mov [ecx].PureEdge@@mRemainingScanLines,ax ; result is mRemainingScanLines cmp ax,00h ; check scanlines==0 je @@loopNext ; if it's zero, continue mov yDestHeight,eax ; set yDestHeight push nextVertex ; save nextVertex value pop [ecx].PureEdge@@mCurrentEdgeEnd ; restore it to mCurrentEdgeEnd getPoint [ecx].PureEdge@@mlpSrcList,startVertex ; get mlpSrcList[startVertex] multiply ax,bmData@@mPrecision ; multiply mxSource by bmData@@mPrecision mov [ecx].PureEdge@@mxSource,eax ; move srcList[startVertex].x() to mxSource multiply bx,bmData@@mPrecision ; multiply mySource by bmData@@mPrecision mov [ecx].PureEdge@@mySource,eax ; move srcList[startVertex].y() to mySource getPoint [ecx].PureEdge@@mlpSrcList,nextVertex ; get mlpSrcList[nextVertex] multiply ax,bmData@@mPrecision ; ax by bmData@@mPrecision mov ebx,[ecx].PureEdge@@mxSource ; mxSource to bx register sub eax,ebx ; (ie) mlpSrcList[nextVertex].x-mxSource-->eax divide eax,yDestHeight ; divide by yDestHeight, this is mxSourceStep mov [ecx].PureEdge@@mxSourceStep,eax ; move eax register into mxSourceStep getPoint [ecx].PureEdge@@mlpSrcList,nextVertex ; get source point mov eax,ebx ; move point.y into eax register multiply ax,bmData@@mPrecision ; multiply by precision mov ebx,[ecx].PureEdge@@mySource ; mySource to bx register sub eax,ebx ; (ie) mlpSrcList[nextVertex].y-mySource-->eax divide eax,yDestHeight ; divide by yDestHeight, this is mySourceStep mov [ecx].PureEdge@@mySourceStep,eax ; move eax register into mySourceStep getPoint [ecx].PureEdge@@mlpDstList,startVertex ; get mlpDstList[startVertex] mov [ecx].PureEdge@@mxDestLocation,ax ; mxDestLocation=mDstList[startVertex].x() getPoint [ecx].PureEdge@@mlpDstList,nextVertex ; get dstList[nextVertex] sub ax,[ecx].PureEdge@@mxDestLocation ; get the width of the segment mov xDestWidth,ax ; move the width into xDestWidth cmp xDestWidth,00h ; is the direction negative (ie) left jl @@negWidth ; yes, handle negative direction mov [ecx].PureEdge@@mxDirection,01h ; set right direction indicator mov [ecx].PureEdge@@mxErrorTerm,00h ; set mxErrorTerm to zero movzx eax,xDestWidth ; move xDestWidth to eax zero extend movzx ebx,[ecx].PureEdge@@mRemainingScanLines ; move mRemainingScanLines to ebx divide eax,ebx ; eax=xDestWidth.mRemainingScanLines mov [ecx].PureEdge@@mxStep,ax ; move result into mxStep jmp @@syncOne ; jump over following handler @@negWidth: ; handle negative direction mov [ecx].PureEdge@@mxDirection,-1 ; set left direction indicator neg xDestWidth ; negate the width (ie) make it positive mov ax,01h ; move one into ax register sub ax,[ecx].PureEdge@@mRemainingScanLines ; subtract remaining scan lines from 1 mov [ecx].PureEdge@@mxErrorTerm,ax ; move result to mxErrorTerm movzx eax,xDestWidth ; move xDestWidth to eax zero extend movzx ebx,[ecx].PureEdge@@mRemainingScanLines ; move mRemainingScanLines to ebx divide eax,ebx ; eax=xDestWidth/mRemainingScanLines neg eax ; negate the result mov [ecx].PureEdge@@mxStep,ax ; move result back into mxStep @@syncOne: ; synchronization address mov [ecx].PureEdge@@mxAdjustUp,dx ; move remainder into mxAdjustUp push [ecx].PureEdge@@mRemainingScanLines ; save mRemainingScanLines pop [ecx].PureEdge@@mxAdjustDown ; restore mRemainingScanLines into mxAdjustDown jmp @@ok ; jump over forever loop @@loopNext: ; forever loop address push nextVertex ; save nextVertex on stack pop [ecx].PureEdge@@mStartVertex ; restore into mStartVertex push nextVertex ; save nextVertex on stack pop startVertex ; restore it to local copy of startVertex jmp @@forever ; continue with loop @@error: ; error handler mov eax,0001h ; set ax register to 01h to indicate failure jmp @@return ; jump over to return label @@ok: ; success handler xor eax,eax ; clear out eax register to handle success @@return: ; return label add esp,LocalLength ; remove local variables from stack pop ebp ; restore old stack frame retn ; return near to caller _setupEdge endp _getMinMaxInfo proc near ; long getMinMaxInfo(void) LOCAL yMin:WORD,yMax:WORD=LocalLength push ebp ; save old stack frame mov ebp,esp ; create new stack frame sub esp,LocalLength ; make room for local variables push ecx ; save callers ecx register mov edx,ecx ; move ecx into edx, edx has ptr to PureEdge cmp [edx].PureEdge@@mNumVertexes,MINVERTEX ; make sure have at least 3 vertexes jl @@error ; handle error condition mov yMin,MINVALUE ; start yMin with some low value mov yMax,MAXVALUE ; start yMax with some high value xor ecx,ecx ; start at index zero mov eax,[edx].PureEdge@@mlpDstList ; move address of (Point*) to ebx register @@iterator: ; loop top mov bx,[eax].Point@@y ; move point::y to bx register cmp bx,yMin ; compare with current yMin value jg @@greater ; point::y greater than current yMin @@nexttest: ; if I handle the greater condition, still need to do less cmp bx,yMax ; compare with current yMax value jl @@less ; point::y less than current yMax jmp @@looptest ; nuthin, continue with test @@greater: ; handle greater condition mov yMin,bx ; set yMin to bx register mov [edx].PureEdge@@mMinVertex,cx ; move index number of vertex to mMinVertex jmp @@nexttest ; go perform next test @@less: ; handle less condition mov yMax,bx ; set yMax to bx register mov [edx].PureEdge@@mMaxVertex,cx ; update mMaxVertex with current index @@looptest: ; falls through to loop add eax,04h ; add 4 bytes to eax to address next (Point*) inc cx ; increment cx register cmp cx,[edx].PureEdge@@mNumVertexes ; have we reeached the number of vertexes yet? jl @@iterator ; still more vertexes push [edx].PureEdge@@mMaxVertex ; save mMaxVertex pop [edx].PureEdge@@mStartVertex ; restore it to mStartVertex jmp @@ok ; error return sync address @@error: ; setup for error return code mov eax,0001h ; move 01h into ax to indicate error jmp @@return ; jump to return label @@ok: ; setup for success return code xor eax,eax ; clear out eax register @@return: ; return label pop ecx ; restore callers ecx register add esp,LocalLength ; pop local variables off stack pop ebp ; restore old stack frame retn ; return near to caller _getMinMaxInfo endp _setSrcBitmapInfo 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 ax,word ptr[ebp+08h] ; move width into ax register mov bmData@@mSrcWidth,ax ; move width into bmData@@mSrcWidth mov bx,word ptr[ebp+0Ch] ; move height into bx register mov bmData@@mSrcHeight,bx ; move height into bx register multiply ax,bx ; multiply (width*height) mov bmData@@mSrcExtent,eax ; (width*height) to mSrcExtent push dword ptr[ebp+10h] ; save lpBitmapImage on stack pop bmData@@mlpSrcPtr ; restore in mlpSrcPtr mov bmData@@mGetCache.GetCache@@mCacheStatus,0FFh mov bmData@@mGetCache.GetCache@@mCacheHits,00000000h ; mov bmData@@mGetCache.Cache@@mColRow,00h ; move zero into cache colRow ; mov bmData@@mGetCache.Cache@@mCacheData,00h ; move zero into cache data ; mov bmData@@mGetCache.Cache@@mCacheStatus,0FFh ; move FFh into cache status pop ebx ; restore ebx register pop eax ; restore eax register pop ebp ; restore old stack frame retn ; return near to caller _setSrcBitmapInfo endp _setDstBitmapInfo proc near ; void setDstBitmapInfo(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 ax,word ptr[ebp+08h] ; move width into ax register mov bmData@@mDstWidth,ax ; move width into mDstWidth mov bx,word ptr[ebp+0Ch] ; move height into bx register mov bmData@@mDstHeight,bx ; move height into mDstHeight multiply ax,bx ; multiply (width*height) mov bmData@@mDstExtent,eax ; move (width*height) into mDstExtent push dword ptr[ebp+10h] ; save lpBitmapImage on stack pop bmData@@mlpDstPtr ; restore in mlpDstPtr mov bmData@@mDstCacheRow,00h ; move zero to cache row mov bmData@@mDstCacheMul,00h ; move zero to cache multiply result pop ebx ; restore ebx register pop eax ; restore eax register pop ebp ; restore old stack frame retn ; return near to caller _setDstBitmapInfo endp public _mapTexture public _initEdge public _setSrcBitmapInfo public _setDstBitmapInfo end