;//////////////////////////////////////////////////////////////////////////
;//                                                                      //
;//              INTEL CORPORATION PROPRIETARY INFORMATION               //
;//                                                                      //
;//      This software is supplied under the terms of a license          //
;//      agreement or nondisclosure agreement with Intel Corporation     //
;//      and may not be copied or disclosed except in accordance         //
;//      with the terms of that agreement.                               //
;//                                                                      //
;//////////////////////////////////////////////////////////////////////////

     ASSUME nothing

memS   EQU   0
?PLM   EQU   0
?WIN   EQU   1

_DATA        SEGMENT DWORD PUBLIC 'DATA'
; locals being kept in data space and not on stack to conserve register usage
ALIGN	4				;align on dword boundary
_DATA		ENDS

.386

ifndef SEGNAME
        SEGNAME equ <_DCISAMP32>
endif

;sBegin  Code
;createSeg %SEGNAME, CodeSeg, word, PUBLIC, use32, CODE
%SEGNAME        SEGMENT WORD PUBLIC USE32 'CODE'

ASSUME cs : _DCISAMP32
ASSUME ds : _DATA
ASSUME es : nothing
ASSUME fs : nothing

PUBLIC _StretchBlit
_StretchBlit PROC FAR
; Set up equates for params
wSrcSel		EQU	WORD	PTR	ss:[ebp+0]      ;source selector
dwibSrc 	EQU	DWORD	PTR	ss:[ebp+2]      ;source offset
dwSrcStride     EQU     DWORD   PTR     ss:[ebp+6]      ;source stride
wDstSel		EQU	WORD	PTR	ss:[ebp+10]     ;dest. selector
dwibDst 	EQU	DWORD	PTR ss:[ebp+12]         ;dest. offse
dwStride	EQU	DWORD	PTR	ss:[ebp+16]     ;dest. stride
dwSrcWidth	EQU	DWORD	PTR ss:[ebp+20]         ;source width
dwSrcHeight	EQU DWORD	PTR ss:[ebp+24]         ;source height
lpXcode		EQU	DWORD	PTR	ss:[ebp+28]     ;horiz. stretch code
lpYcode		EQU	DWORD	PTR	ss:[ebp+32]     ;vert. stretch code
dwDstWidth	EQU DWORD	PTR ss:[ebp+36]         ;dest. width

; set up stack frame
	push	ebp
    push	edi
    push	esi
	push	ds
    movzx	ebp, sp			; bp now pointing to last pushed reg
	add		ebp, 20			; inc past pushed regs and ret addr

; set up register usage

	xor		eax, eax
	mov		ax, wSrcSel
	mov		ds, ax
	mov		esi, dwibSrc	; ds:esi now points to src buffer

	mov		es,	wDstSel
	mov		edi, dwibDst	; es:edi now points to dst buffer

	xor		edx, edx
	lfs		dx, lpXcode		; fs:[edx] now points to X stretch code

	xor		ebx, ebx
	lgs		bx, lpYcode		; gs:[ebx] now points to Y stretch code

;; ds:esi <-- points to src buffer
;; es:edi <-- points to dst buffer
;; fs:edx <-- points to X stretch code
;; gs:ebx <-- points to Y stretch code

;	for (i = 0; i < srcHeight; i++)
;	{
;		for (j = 0; j < srcWidth; j++)
;		{
;			for (k = vcode[i]; k > 0; k--)
;			{
;				for (l = hcode[j]; l > 0; l--)
;				{
;					*MyDstPtr++ = *MySrcPtr;
;				}
;				MyDstPtr -= hcode[j];
;				MyDstPtr += stride;
;			}
;			MyDstPtr -= vcode[i]*stride;
;			MyDstPtr += hcode[j];
;			MySrcPtr++;
;		}
;		MyDstPtr += vcode[i]*stride
;	}

	xor		ecx, ecx
	xor		eax, eax

	I_loop:	   
		push	ecx
		xor		ecx, ecx
		xor		edx, edx
		lfs		dx, lpXcode		
		
		J_loop:
			push	ecx
			xor		ecx, ecx
			mov		cl, gs:[ebx] 	; ecx = vcode[i]
			cmp		ecx, 0
			jz		K_Is_Zero

			K_loop:
				push	ecx				; stack = K
				mov		cl, fs:[edx] 	; L = hcode[j]
				cmp		ecx, 0
				jz		L_Is_Zero
				push	ecx				; stack = L
				xor		eax, eax
				mov		al, ds:[esi]	; eax = *MySrcPtr

				L_loop:
					mov		es:[edi], al	; *MyDstPtr = *MySrcPtr;
					inc		edi				; MyDstPtr++
					dec		ecx				; ecx == L
					jnz		L_loop

				pop		eax				; eax = stack = hcode[j]
				sub		edi, eax		; MyDstPtr -= hcode[j];
				mov		eax, dwStride	
				add		edi, eax		; MyDstPtr += stride;
				pop		ecx				; ecx == K
				dec		ecx				
				jnz		K_loop
				
			push	edx				; save hcode offset
			xor		eax, eax
			mov		al, gs:[ebx]
			mul		dwStride
			sub		edi, eax		; MyDstPtr -= vcode[i]*stride;
			pop		edx				; restore hcode offset
			jmp		LPositive

		L_Is_Zero:
			pop		eax				; pop leftover K index
		LPositive:
			xor		eax, eax
			mov		al, fs:[edx]  
			add		edi, eax  		; MyDstPtr += hcode[j];
			inc		esi				; MySrcPtr++;
			inc		edx				; hcode++
			pop		ecx				; ecx == J
			inc		ecx				
			cmp		ecx, dwSrcWidth 
			jl		J_loop
			
		sub		edi, dwDstWidth
		xor		eax, eax
		jmp		KPositive

	K_Is_Zero:
		pop		ecx				; pop leftover J index
		add		esi, dwSrcWidth ; skipped a line, so add a line to src. pointer
	KPositive:
		xor		eax, eax
		mov		al, gs:[ebx]	; ecx = vcode[i]
 		mul		dwStride
 		inc		ebx				; vcode++
		add		edi, eax		; MyDstPtr += vcode[i]*stride				
                mov             eax, dwSrcStride
                sub             eax, dwSrcWidth
                add             esi, eax
		pop		ecx		  		; ecx == i
		inc		ecx
		cmp		ecx, dwSrcHeight 
		jl		I_loop

	xor		ebx, ebx        	; clean up code. Clear seg registers. Pop saved registers.
	mov		fs,  bx
	pop		ds      
	pop		esi             
	pop		edi             
	pop		ebp             
	db		66h             	; toggle to 16bit style return
	retf

_StretchBlit endp

%SEGNAME ENDS
end
