Files
Work/engine/TMAP16.ASM
2024-08-07 09:16:27 -04:00

589 lines
37 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;*************************************************************************************
; MODULE: TMAP16.ASM DATE: DECEMBER 28,1994
; AUTHOR: SEAN M. KESSLER
; TARGET: 16 BIT TARGET
; FUNCTION : TEXTURE MAPPING POLYGONS IN PERSPECTIVE
;*************************************************************************************
.MODEL LARGE C
.386
.DATA
bmData@@mSrcWidth DW 00h
bmData@@mSrcHeight DW 00h
bmData@@mlpSrcPtr DD 00h
bmData@@mDstWidth DW 00h
bmData@@mDstHeight DW 00h
bmData@@mlpDstPtr DD 00h
MINVALUE EQU -32767
MAXVALUE EQU 32767
MINVERTEX EQU 3
PRECISION EQU 16384
.CODE
LOCALS
INCLUDE ..\COMMON\COMMON.INC
INCLUDE ..\ENGINE\TMAP16.INC
round MACRO varOne
mov eax,varOne ; move varOne into eax register
mov ebx,eax ; move varOne into ebx register
and ebx,00003FFFh ; get remainder into ebx register
shr eax,14 ; get whole number to eax register
cmp ebx,8192 ; if remainder > 8192, increment eax
db 7Eh ; the next 2 bytes comprise "jle +2" (ie)
db 02h ; jump passed the increment eax instruction
inc eax ; increment value in eax
ENDM
multiply MACRO varOne,varTwo
push bx ; save bx register
mov ax,varOne ; move varOne into ax register
mov bx,varTwo ; move varTwo into bx register
imul bx ; perform the multiply result to dx:ax
push ax ; save ax register result
movzx eax,dx ; move dx register to eax zero extend
shl eax,16 ; shift eax left by a word
pop ax ; restore ax register result
pop bx ; restore bx register
ENDM
divide MACRO varOne,varTwo
push ebx ; save ebx register
mov ebx,varTwo ; move varTwo into ebx register
mov eax,varOne ; move varOne into eax register
cdq ; convert doubleword in eax to quadword at edx:eax
idiv ebx ; divide eax/ebx result to eax, remainder to edx
pop ebx ; restore ebx register
ENDM
getPoint MACRO segment,offset,index
push si ; save source index register
push ds ; save data segment register
push cx ; save cx register
push segment ; save segment on stack
pop ds ; restore to data segment
mov ax,index ; move index to ax register
shl ax,02h ; multiply ax by size of far pointer
mov si,offset ; now move offset address to si
add si,ax ; add in the increment value
xor eax,eax ; clear out eax register
mov ax,ds:[si].Point@@x ; get the x-value to ax register
xor ebx,ebx ; clear out ebx register
mov bx,ds:[si].Point@@y ; get the y-value to bx register
pop cx ; restore saved cx register
pop ds ; restore saved data segment
pop si ; restore save source index register
ENDM
_initEdge proc far ; void initEdge(short edgeType,PureEdge *lpEdge);
push bp ; save callers stack frame
mov bp,sp ; create new stack frame
push di ; save callers destination index register
mov es,[bp+10] ; move segment of data to extra segment
mov di,[bp+8] ; move offset of data to destination index register
assume es ; now assume extra segment for segment loads.
call _getMinMaxInfo ; find minimum and maximum vertexes
cmp ax,00h ; make sure previous call returned success
jne @@return ; if not then we should leave
push word ptr[bp+6] ; push edgeType (-1:leftEdge,1:rightEdge)
push [di].PureEdge@@mStartVertex ; push startVertex
call _setupEdge ; now setup the edge
add sp,04h ; readjust the stack
@@return:
assume @data ; assume old data segment for segment loads
pop di ; restore destination index register
pop bp ; restore callers stack frame
retf ; return to caller
_initEdge endp
_getMinMaxInfo proc near ; short getMinMaxInfo(void)
LOCAL yMin:WORD,yMax:WORD=LocalLength
push bp ; save callers stack frame
mov bp,sp ; create new frame
sub sp,LocalLength ; adjust stack to handle local variables
push cx ; save callers cx register
push si ; save callers source index register
push ds ; save callers data segment register
cmp [di].PureEdge@@mNumVertexes,MINVERTEX ; make sure have at least three vertexes
jl @@error ; otherwise we've got a problem
mov yMin,MINVALUE ; start yMin with some low value
mov yMax,MAXVALUE ; start yMax with some high value
xor cx,cx ; start at index 0
mov ds,[di].PureEdge@@mlpDstList ; segment address of (Point *) to extra segment register
mov si,[di].PureEdge@@mlpDstList+2 ; offset address of (Point *) to source index register
@@iterator: ; loop top
mov bx,ds:[si].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 equal condition
mov yMin,bx ; set yMin to bx register
mov [di].PureEdge@@mMinVertex,cx ; move index number of vertex to mMinVertex
jmp @@nexttest ; go perform next test
@@less: ; handle less equal condition
mov yMax,bx ; set yMax to bx register
mov [di].PureEdge@@mMaxVertex,cx ; update mMaxVertex with current index
@@looptest: ; falls through to loop
add si,04h ; add 2 bytes to si to bump to next (Point*)
inc cx ; increment cx
cmp cx,[di].PureEdge@@mNumVertexes ; have we reached the number of vertexes yet?
jl @@iterator ; still more vertexes
push [di].PureEdge@@mMaxVertex ; save mMaxVertex
pop [di].PureEdge@@mStartVertex ; restore it to mStartVertex
jmp @@ok ; ok we've got good number of vertexes
@@error: ; setup for error return code
mov ax,01h ; move 01h into ax to indicate error
jmp @@return ; jump to return label
@@ok: ; setup for success return code
xor ax,ax ; clear out ax register
@@return: ; return label
pop ds ; restore callers extra segment register
pop si ; restore callers source index register
pop cx ; restore callers cx register
add sp,LocalLength ; readjust stack for local variables
pop bp ; restore old frame
retn ; return to caller
_getMinMaxInfo endp
_setupEdge proc near ; short setupEdge(short edgeType,short startVertex)
LOCAL nextVertex:WORD,xDestWidth:WORD,yDestHeight:DWORD=LocalLength
push bp ; save old stack frame
mov bp,sp ; create new stack frame
sub sp,LocalLength ; make room for local variables
push si ; save source index register
push ds ; save data segment register
push word ptr[bp+6] ; save edgeType on stack
pop [di].PureEdge@@mEdgeDirection ; restore edgeType to mEdgeDirection
push word ptr[bp+4] ; save startVertex on stack
pop [di].PureEdge@@mStartVertex ; restore startVertex to mStartVertex
@@forever: ; forever loop label
mov bx,[di].PureEdge@@mStartVertex ; move mStartVertex to bx register
cmp bx,[di].PureEdge@@mMinVertex ; is mStartVertex same as mMinVertex ??
je @@error ; if yes then return error status
add bx,[di].PureEdge@@mEdgeDirection ; add edge direction to mStartVertex
mov nextVertex,bx ; move result to nextVertex
mov bx,[di].PureEdge@@mNumVertexes ; move number of vertexes to bx register
cmp nextVertex,bx ; compare nextVertex to number of vertexes
jge @@zervert ; nextVertex is greater eq number of vertexes
cmp nextVertex,00h ; compare nextVertex to zero
jl @@adjVert ; nextVertex is less than zero
jmp @@bypass ; nextVertex is fine
@@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:
getPoint [di].PureEdge@@mlpDstList,[di].PureEdge@@mlpDstList+2,nextVertex
push bx ; dstList[nextVertex].y() in bx , save it
getPoint [di].PureEdge@@mlpDstList,[di].PureEdge@@mlpDstList+2,[di].PureEdge@@mStartVertex
pop ax ; restore first x-point to ax
sub ax,bx ; now subtract second x-point
mov [di].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 [di].PureEdge@@mCurrentEdgeEnd ; restore it to mCurrentEdgeEnd
getPoint [di].PureEdge@@mlpSrcList+2,[di].PureEdge@@mlpSrcList,[di].PureEdge@@mStartVertex
multiply ax,PRECISION ; multiply mxSource by PRECISION
mov [di].PureEdge@@mxSource,eax ; move srcList[mStartVertex].x() to mxSource
multiply bx,PRECISION ; multiply mySource by PRECISION
mov [di].PureEdge@@mySource,eax ; move srcList[mStartVertex].y() to mySource
getPoint [di].PureEdge@@mlpSrcList+2,[di].PureEdge@@mlpSrcList,nextVertex ; get source point
multiply ax,PRECISION
mov ebx,[di].PureEdge@@mxSource ; mxSource to bx register
sub eax,ebx ; (ie) mlpSrcList[nextVertex].x-mxSource-->ax
divide eax,yDestHeight ; divide by yDestHeight, this is mxSourceStep
mov [di].PureEdge@@mxSourceStep,eax ; move eax register into mxSourceStep
getPoint [di].PureEdge@@mlpSrcList+2,[di].PureEdge@@mlpSrcList,nextVertex ; get source point
mov eax,ebx ; move point.y into ax register
multiply ax,PRECISION
mov ebx,[di].PureEdge@@mySource ; mySource to bx register
sub eax,ebx ; (ie) mlpSrcList[nextVertex].y-mySource-->ax
divide eax,yDestHeight ; divide by yDestHeight, this is mySourceStep
mov [di].PureEdge@@mySourceStep,eax ; move eax register into mySourceStep
getPoint [di].PureEdge@@mlpDstList,[di].PureEdge@@mlpDstList+2,[di].PureEdge@@mStartVertex
mov [di].PureEdge@@mxDestLocation,ax ; mxDestLocation=mDstList[mStartVertex].x()
getPoint [di].PureEdge@@mlpDstList,[di].PureEdge@@mlpDstList+2,nextVertex ; get dstList[nextVertex]
sub ax,[di].PureEdge@@mxDestLocation ; get the width of the segment
mov xDestWidth,ax ; move width into xDestWidth
cmp xDestWidth,00h ; is the direction negative (ie) left
jl @@negWidth ; yes, handle negative direction
mov [di].PureEdge@@mxDirection,01h ; set right direction indicator
mov [di].PureEdge@@mxErrorTerm,00h ; set mxErrorTerm to zero
movzx eax,xDestWidth ; move xDestWidth to eax zero extend
movzx ebx,[di].PureEdge@@mRemainingScanLines ; move mRemainingScanLines to ebx zero extend
divide eax,ebx ; eax=xDestWidth/mRemainingScanLines
mov [di].PureEdge@@mxStep,ax ; move result into mxStep
jmp @@syncOne ; jump over following handler
@@negWidth: ; handle negative direction
mov [di].PureEdge@@mxDirection,-1 ; set left direction indicator
neg xDestWidth ; negate the width (ie) make it positive
mov ax,01h ; move a 1 into ax register
sub ax,[di].PureEdge@@mRemainingScanLines ; subtract remaining scan lines from 1
mov [di].PureEdge@@mxErrorTerm,ax ; move result to mxErrorTerm
movzx eax,xDestWidth ; move xDestWidth to eax zero extend
movzx ebx,[di].PureEdge@@mRemainingScanLines ; move mRemainingScanLines to ebx zero extend
divide eax,ebx ; eax=xDestWidth/mRemainingScanLines
neg eax ; negate the result
mov [di].PureEdge@@mxStep,ax ; move result back into mxStep
@@syncOne: ; synchronization address
movzx eax,xDestWidth ; move xDestWidth into eax register, zero extend
movzx ebx,[di].PureEdge@@mRemainingScanLines ; move mRemainingScanLines into ebx register
divide eax,ebx ; divide xDestWidth/mRemainingScanLines
mov [di].PureEdge@@mxAdjustUp,dx ; move remainder into mxAdjustUp
push [di].PureEdge@@mRemainingScanLines ; save mRemainingScanLines
pop [di].PureEdge@@mxAdjustDown ; restore mRemainingScanLines into mxAdjustDown
jmp @@ok ; jump over forever loop
@@loopNext: ; forever loop address
push nextVertex ; save nextVertex on stack
pop [di].PureEdge@@mStartVertex ; restore to mStartVertex
jmp @@forever ; continue with loop
@@error: ; error handler
mov ax,01h ; set ax register to 01h to indicate failure
jmp @@return ; jump over to return label
@@ok: ; success handler
xor ax,ax ; clear out ax register to handle success
@@return: ; return label
pop ds ; restore data segment register
pop si ; restore source index register
add sp,LocalLength ; readjust stack for local variables
pop bp ; restore old stack frame
retn ; return to caller
_setupEdge endp
_increment proc near ; short increment(PureEdge *lpEdge)
push bp ; save callers stack frame
mov bp,sp ; create new stack frame
push es ; save extra segment register
push di ; save destination index register
mov es,[bp+6] ; move segment of data to extra segment
mov di,[bp+4] ; move offset of data to destination index register
assume es ; now assume extra segment for segment loads.
dec [di].PureEdge@@mRemainingScanLines ; decrement mRemainingScanLines
cmp [di].PureEdge@@mRemainingScanLines,00h ; compare mRemainingScanLines to zero
je @@newEdge ; no more scan lines, try to get to next edge
jmp @@syncOne ; more scan lines, keep going
@@newEdge: ; new edge handler
push [di].PureEdge@@mEdgeDirection ; save edgeDirection
push [di].PureEdge@@mCurrentEdgeEnd ; save currentEdge end (ie) nextEdge index
call _setupEdge ; attempt to setup new edge
add sp,04h ; readjust stack
cmp ax,01h ; did prior call fail?
je @@error ; yes, no more edges
jmp @@ok ; no, keep going
@@syncOne: ; synchronizing address
mov eax,[di].PureEdge@@mxSourceStep ; get mxSourceStep to eax register
add eax,[di].PureEdge@@mxSource ; add in mxSource
mov [di].PureEdge@@mxSource,eax ; replace mxSource with new value
mov eax,[di].PureEdge@@mySourceStep ; get mySourceStep into eax register
add eax,[di].PureEdge@@mySource ; add in mySource
mov [di].PureEdge@@mySource,eax ; replace mySource with new value
mov ax,[di].PureEdge@@mxDestLocation ; get mxDestLocation into ax register
add ax,[di].PureEdge@@mxStep ; add in mxStep
mov [di].PureEdge@@mxDestLocation,ax ; replace mxDestLocation with new value
mov ax,[di].PureEdge@@mxErrorTerm ; get mxErrorTerm to ax register
add ax,[di].PureEdge@@mxAdjustUp ; add in mxAdjustUp
mov [di].PureEdge@@mxErrorTerm,ax ; replace mxErrorTerm with new value
cmp ax,00h ; now compare result to 00h
jg @@adjTerm ; result is greater than zero
jmp @@ok ; result is less equal to zero, we're done
@@adjTerm:
mov ax,[di].PureEdge@@mxDestLocation ; get mxDestLocation to ax register
add ax,[di].PureEdge@@mxDirection ; add in mxDirection
mov [di].PureEdge@@mxDestLocation,ax ; replace mxDestLocation with new value
mov ax,[di].PureEdge@@mxErrorTerm ; move mxErrorTerm into ax register
sub ax,[di].PureEdge@@mxAdjustDown ; add in mxAdjustDown
mov [di].PureEdge@@mxErrorTerm,ax ; replace mxErrorTerm with new value
@@ok: ; ok handler address
xor ax,ax ; set 00h into ax register
jmp @@return ; jump passed next block
@@error: ; error handler address
mov ax,01h ; set 01h into ax register
@@return: ; return handler
assume @data ; assume old data segment for segment loads
pop di ; restore destination index register
pop es ; restore extra segment register
pop bp ; restore stack frame
retn ; return to caller
_increment endp
_mapTexture proc far ; void mapTexture(PureMap *lpTextureMap)
push bp ; save stack frame
mov bp,sp ; create new frame
push di ; save destination index register
push si ; save source index register
push ds ; save data segment register
mov es,word ptr[bp+8] ; move segment (PureMap*) to es register
mov di,word ptr[bp+6] ; move offset (PureMap*) to destination index register
push es:[di].PureMap@@mlpLeftEdge+2 ; save segment mlpLeftEdge
pop ds ; restore segment mlpLeftEdge to ds register
mov si,es:[di].PureMap@@mlpLeftEdge ; move offset mlpLeftEdge to si register
mov cx,ds:[si].PureEdge@@mMaxVertex ; move left edge max vertex to ax register
getPoint ds:[si].PureEdge@@mlpDstList,ds:[si].PureEdge@@mlpDstList+2,cx
mov es:[di].PureMap@@myValue,bx ; myValue=mLeftEdge[mLeftEdge.maxVertex()].y()
@@forever: ; while(TRUE)
push es ; push segment (PureMap*)
push di ; push offset (PureMap*)
call _scanOutputLine ; call scanOutputLine
add sp,04h ; readjust stack
push word ptr es:[di].PureMap@@mlpLeftEdge+2 ; push segment mlpLeftEdge
push word ptr es:[di].PureMap@@mlpLeftEdge ; push offset mlpLeftEdge
call _increment ; increment along left edge
add sp,04h ; readjust stack after call
cmp ax,00h ; check return code
jne @@return ; edge failed to increment, we're done
push word ptr es:[di].PureMap@@mlpRightEdge ; push segment mlpRightEdge
push word ptr es:[di].PureMap@@mlpRightEdge+2 ; push offset mlpRightEdge
call _increment ; increment along right edge
add sp,04h ; readjust stack after call
cmp ax,00h ; check return code
jne @@return ; edge failed to increment, we're done
inc es:[di].PureMap@@myValue ; increment y() position
jmp @@forever ; loop until all edges are completed
@@return: ; return address label
pop ds ; restore data segment register
pop si ; restore source index re
pop di ; restore destination index register
pop bp ; restore old frame
retf ; return to caller
_mapTexture endp
_scanOutputLine proc near
push bp ; save stack frame
mov bp,sp ; create new frame
push es ; save extra segment
push di ; save destination index register
push ds ; save data segment register
push si ; save source index register
mov es,word ptr[bp+6] ; move segment (PureMap*) to extra segment register
mov di,word ptr[bp+4] ; move offset (PureMap*) to destination index register
push es:[di].PureMap@@mlpLeftEdge+2 ; save segment mlpLeftEdge
pop ds ; restore segment mlpLeftEdge to data segment
mov si,es:[di].PureMap@@mlpLeftEdge ; move offset mlpLeftEdge to source index reg
mov eax,ds:[si].PureEdge@@mxSource ; move PureEdge::mxSource to eax register
mov es:[di].PureMap@@mxSource,eax ; move PureEdge::mxSource to PureMap::mxSource
mov eax,ds:[si].PureEdge@@mySource ; move PureEdge::mySource to eax register
mov es:[di].PureMap@@mySource,eax ; move PureEdge::mySource to PureMap::mySource
mov bx,ds:[si].PureEdge@@mxDestLocation ; move PureEdge::mxDestLocation to bx
mov es:[di].PureMap@@mxDest,bx ; move PureEdge::mxDestLocation to PureMap::mxDest
push word ptr es:[di].PureMap@@mlpRightEdge ; save segment mlpRightEdge
pop ds ; restore segment mlpRightEdge to ds
mov si,word ptr es:[di].PureMap@@mlpRightEdge+2 ; move offset mlpRightEdge to si
xor eax,eax ; to clear out the high word of eax
mov ax,ds:[si].PureEdge@@mxDestLocation ; move PureEdge.mxDestLocation to ax
mov es:[di].PureMap@@mxDestMax,ax ; move PureEdge.mxDestLocation to PureMap.mxDestMap
sub ax,bx ; mxDestMax-mxDest
cmp ax,00h ; check if width is zero
je @@return ; if width is zero just return
mov es:[di].PureMap@@mDestWidth,eax ; move width into PureMap::mDestWidth
mov eax,ds:[si].PureEdge@@mxSource ; move PureEdge::mxSource into eax
sub eax,es:[di].PureMap@@mxSource ; subtract out PureMap::mxSource
divide eax,es:[di].PureMap@@mDestWidth ; now divide by PureMap::mDestWidth
mov es:[di].PureMap@@mxSourceStep,eax ; move new value to PureMap@@mxSourceStep
mov eax,ds:[si].PureEdge@@mySource ; move PureEdge::mySource into eax
sub eax,es:[di].PureMap@@mySource ; subtract out PureMap::mySource
divide eax,es:[di].PureMap@@mDestWidth ; now divide by PureMap::mDestWidth
mov es:[di].PureMap@@mySourceStep,eax ; move new value to PureMap@@mySourceStep
@@xLoop: ; xLoop top
mov ax,es:[di].PureMap@@mxDest ; move mxDest to ax register
cmp ax,es:[di].PureMap@@mxDestMax ; compare mxDest to mxDestMax
jge @@return ; if its greater equal return
cmp es:[di].PureMap@@mxSource,00h ; compare mxSource to zero
jl @@xFix ; if mxSource is less than zero, fix
@@nxtChk: ; sync label to continue with checking
cmp es:[di].PureMap@@mySource,00h ; compare mySource to zero
jl @@yFix ; if mySource is less than zero, fix
jmp @@syncOne ; everything ok, jump over block
@@yFix: ; handle y-fixup
mov es:[di].PureMap@@mySource,00h ; move zero to mySource
jmp @@syncOne ; jump around next handler
@@xFix: ; handle x-fixup
mov es:[di].PureMap@@mxSource,00h ; move zero into mxSource
jmp @@nxtChk ; now look at y-value
@@syncOne: ; synchronization for conditionals
push es ; save extra segment register
mov eax,es:[di].PureMap@@mySource ; move PureMap@@mxSource to eax
round eax ; convert and round
push ax ; save result on stack
mov eax,es:[di].PureMap@@mxSource ; move PureMap@@mySource to eax
round eax ; convert and round
shl eax,16 ; now shift eax left by 16 bits
pop ax ; and restore yValue to low word
movzx ebx,es:[di].PureMap@@mxDest ; move PureMap::mxDest to eax
shl ebx,16 ; shift eax left 16 bits
mov bx,es:[di].PureMap@@myValue ; move PureMap::myValue to ax
call _putImageBits ; call put pixel handler
pop es ; restore extra segment register
mov eax,es:[di].PureMap@@mxSource ; move mxSource to eax register
add eax,es:[di].PureMap@@mxSourceStep ; add in mxSourceStep
mov es:[di].PureMap@@mxSource,eax ; move result to mxSource
mov eax,es:[di].PureMap@@mySource ; move mySource into eax register
add eax,es:[di].PureMap@@mySourceStep ; add in mySourceStep
mov es:[di].PureMap@@mySource,eax ; move result to mySource
inc es:[di].PureMap@@mxDest ; increment loop counter
jmp @@xLoop ; loop through xLoop
@@return: ; return sync label
pop si ; restore source index register
pop ds ; restore data segment register
pop di ; restore destination index register
pop es ; restore extra segment
pop bp ; restore old stack frame
retn ; return to caller
_scanOutputLine endp
_getSrcDataByte proc near ; BYTE getSrcDataByte(WORD row,WORD col)
LOCAL addValue:DWORD=LocalLength
push bp ; save old stack frame
mov bp,sp ; create new stack frame
sub sp,LocalLength ; adjust stack for local variable
push bx ; save bx register
push cx ; save cx register
push dx ; save dx register
push es ; save extra segment register
push di ; save destination index register
mov dx,word ptr[bp+04h] ; move row into dx register
cmp dx,bmData@@mSrcHeight ; is row greater than bitmap height
jge @@error ; if so then return
cmp dx,00h ; is row less than zero
jl @@error ; if so then return error
movzx ebx,word ptr[bp+06h] ; move col into bx register, zero extended
cmp bx,bmData@@mSrcWidth ; is col greater than bitmap width
jge @@error ; if so then return
cmp bx,00h ; is col less than zero
jl @@error ; is so then return error
movzx ecx,bmData@@mSrcWidth ; move width into cx register
mov ax,bmData@@mSrcHeight ; move height into ax register
push dx ; save dx register
multiply ax,cx ; multiply width*height result to eax
pop dx ; restore dx register
mov addValue,eax ; store result to addValue
multiply dx,cx ; multiply row*width result to eax
add eax,ecx ; add (row*width)+width
sub addValue,eax ; calculate addValue-subValue
movzx eax,word ptr[bp+06h] ; move col into bx register, zero extended
add addValue,eax ; now add the column number back in
mov dx,word ptr addValue+02h ; move high word addValue to dx register
mov ax,word ptr addValue ; move low word addValue to ax register
add ax,word ptr bmData@@mlpSrcPtr ; add low word mlpSrcPtr to low word addValue
adc dx,0000h ; add any carry to high word addValue (dx)
shl dx,03h ; multiply dx register by 8 (segment magic)
add dx,word ptr bmData@@mlpSrcPtr+02h ; now add in high word of mlpSrcData
mov es,dx ; move segment into extra segment register
mov di,ax ; move offset into destination index register
xor ax,ax ; clear out ax register
mov al,byte ptr es:[di] ; move byte value into al register
jmp @@return ; jump over error return code
@@error: ; error return label
mov ax,0FF00h ; error places 0FFh in al register
@@return: ; normal return label
pop di ; restore destination index register
pop es ; restore extra segment register
pop dx ; restore dx register
pop cx ; restore cx register
pop bx ; restore bx register
add sp,LocalLength ; adjust stack for local variable
pop bp ; restore stack frame
retn ; return near to caller
_getSrcDataByte endp
_setDstDataByte proc near ; void setDstDataByte(WORD row,WORD col,BYTE byteValue)
LOCAL addValue:DWORD=LocalLength
push bp ; save old stack frame
mov bp,sp ; create new stack frame
sub sp,LocalLength ; adjust stack for local variable
push ax ; save ax register
push bx ; save bx register
push cx ; save cx register
push dx ; save dx register
push es ; save extra segment register
push di ; save destination index register
mov dx,word ptr[bp+04h] ; move row into dx register
cmp dx,bmData@@mDstHeight ; is row greater than bitmap height
jge @@error ; if so then return
cmp dx,00h ; is row less than zero
jl @@error ; if so then return error
movzx ebx,word ptr[bp+06h] ; move col into bx register, zero extended
cmp bx,bmData@@mDstWidth ; is col greater than bitmap width
jge @@error ; if so then return
cmp bx,00h ; is col less than zero
jl @@error ; if so then return error
movzx ecx,bmData@@mDstWidth ; move width into cx register
mov ax,bmData@@mDstHeight ; move height into ax register
push dx ; save dx register
multiply ax,cx ; multiply width*height result to eax
pop dx ; restore dx register
mov addValue,eax ; store result to addValue
multiply dx,cx ; multiply row*width result to eax
add eax,ecx ; add (row*width)+width
sub addValue,eax ; calculate addValue-subValue
movzx eax,word ptr[bp+06h] ; move col into bx register, zero extended
add addValue,eax ; now add the column number back in
mov dx,word ptr addValue+02h ; move high word addValue to dx register
mov ax,word ptr addValue ; move low word addValue to ax register
add ax,word ptr bmData@@mlpDstPtr ; add low word mlpSrcPtr to low word addValue
adc dx,0000h ; add any carry to high word addValue (dx)
shl dx,03h ; multiply dx register by 8 (segment magic)
add dx,word ptr bmData@@mlpDstPtr+02h ; now add in high word of mlpSrcData
mov es,dx ; move segment into extra segment register
mov di,ax ; move offset into destination index register
mov ax,word ptr[bp+08h] ; move byteValue into ax register
mov byte ptr es:[di],al ; move byte value into mlpDstPtr
jmp @@return ; jump over error return code
@@error: ; error return label
mov ax,0FF00h ; error places 0FFh in al register
jmp @@return ; return
@@return: ; normal return label
pop di ; restore destination index register
pop es ; restore extra segment register
pop dx ; restore dx register
pop cx ; restore cx register
pop bx ; restore bx register
pop ax ; restore ax register
add sp,LocalLength ; adjust stack for local variable
pop bp ; restore stack frame
retn ; return near to caller
_setDstDataByte endp
_putImageBits proc near ; void putImageBits(eax dstPoints,ebx srcPoints)
mov cx,ax ; move low word eax to cx register
shr eax,16 ; move high word eax to ax
push ebx ; save ebx register
push ax ; save high word on stack
push cx ; save low word on stack
call _getSrcDataByte ; get source data byte result is in al
add sp,04h ; caller adjusts stack after return
pop ebx ; restore ebx register
cmp ah,0FFh ; check return code
je @@return ; if al==0xFFh call failed
push ax ; push data byte
mov cx,bx ; move low word destination to cx register
shr ebx,16 ; move high word destination to bx
push bx ; save high word on stack
push cx ; save low word on stack
call _setDstDataByte ; set destination data byte
add sp,06h ; caller adjusts stack after return
@@return: ; return label
retn ; return near to caller
_putImageBits endp
_setSrcBitmapInfo proc far ; void setSrcBitmapInfo(WORD width,WORD height,UHUGE *lpBitmapImage)
push bp ; save old stack frame
mov bp,sp ; create new stack frame
push dword ptr[bp+0Ah] ; push lpBitmapImage onto stack
pop bmData@@mlpSrcPtr ; resore into mlpSrcPtr
push word ptr[bp+08h] ; push srcBitmapHeight onto stack
pop bmData@@mSrcHeight ; restore into mSrcHeight
push word ptr[bp+06h] ; push srcBitmapWidth
pop bmData@@mSrcWidth ; restore into mSrcWidth
pop bp ; restore old stack frame
retf ; return far to caller
_setSrcBitmapInfo endp
_setDstBitmapInfo proc far ; void setSrcBitmapInfo(WORD width,WORD height,UHUGE *lpBitmapImage)
push bp ; save old stack frame
mov bp,sp ; create new stack frame
push dword ptr[bp+0Ah] ; push lpBitmapImage onto stack
pop bmData@@mlpDstPtr ; resore into mlpSrcPtr
push word ptr[bp+08h] ; push srcBitmapHeight onto stack
pop bmData@@mDstHeight ; restore into mSrcHeight
push word ptr[bp+06h] ; push srcBitmapWidth
pop bmData@@mDstWidth ; restore into mSrcWidth
pop bp ; restore old stack frame
retf ; return far to caller
_setDstBitmapInfo endp
public _initEdge
public _mapTexture
public _setSrcBitmapInfo
public _setDstBitmapInfo
end