;///////////////////////////////////////////////////////////////////////////////
;/// @file strcmp.asm
;///
;/// @brief Destiny3D Memory Manager strcmp replacement
;///
;/// @author Lightning
;///
;/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
;/// contents of this file is subject to the Destiny3D Member License which
;/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
;///
;/// This file is distributed "AS IS" without warranty of any kind.  Novus
;/// Delta, LLC. does not guarantee the fitness of the contents of this file
;/// for any particular purpose.
;///
;/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
;///
;/// <hr>
;///                                 Change History
;/// <hr>
;///
;/// @date May 2001
;/// @author Lightning
;/// @remarks Creation
;///
;///////////////////////////////////////////////////////////////////////////////

.586p					;pentium commands allowed
.mmx					;MMX allowed
.k3d					;3DNow allowed
.model flat, C

.CODE

;i take care of pushing and popping edi, esi, ebp, and ebx if I need to use them
;as it makes it easier to cut down on the code that the function goes thru

Internal_ASM_strcmp proc
	;Paramaters, char *Str1, char *Str2

	push ebx
	mov ebx, esp
	align 4
	mov edx, [ebx+08h]	;Str1
	mov ecx, [ebx+0Ch]	;Str2

	test edx, 3
	jz StrCmpLoop
	
	;uh oh, someone decided not to start on a 4 byte boundry so we have to adjust
	mov ebx, edx
	and ebx, 3
	jmp dword ptr AlignArray[ebx * 4]

	AlignArray dd 0, Align1, Align2, Align3

	Align1:
		sub edx, 3
		sub ecx, 3
		mov eax, [edx]
		mov ebx, [ecx]
		and eax, 0FF000000h
		and ebx, 0FF000000h
		cmp eax, ebx
		je short StrCmpLoop
		jb short Found0_Neg
		jg short Found0_Pos

	Align2:
		sub edx, 2
		sub ecx, 2
		mov eax, [edx]
		mov ebx, [ecx]
		and eax, 0FFFF0000h
		and ebx, 0FFFF0000h

		bswap eax
		bswap ebx

		cmp eax, ebx
		je short StrCmpLoop
		jb short Found0_Neg
		jg short Found0_Pos

	Align3:
		dec edx
		dec ecx
		mov eax, [edx]
		mov ebx, [ecx]

		and eax, 0FFFFFF00h
		and ebx, 0FFFFFF00h

		bswap eax
		bswap ebx

		cmp eax, ebx
		jb short Found0_Neg
		jg short Found0_Pos

	StrCmpLoop:
		mov eax, [edx]

		;test every byte from right to left for the null
		;you may notice i am only checking eax, if the strings are equal, the null's
		;will line up, if they aren't then they will fail when the null is found
		and al, 0FFh
		jz short Found0_1

		and ah, 0FFh
		jz short Found0_2

		test eax, 000FF0000h
		jz short Found0_3

		mov ebx, [ecx]

		test eax, 0FF000000h
		jz short StrCmpLoop_End

		add edx, 4
		add ecx, 4
		cmp eax, ebx
		je short StrCmpLoop

		;we have to swap the bytes around for our cmp to see if it is above or below
		;otherwise we might return the wrong value
		bswap eax
		bswap ebx

		cmp eax, ebx
		jb short Found0_Neg

	;these functions were moved up to allow the byte checking at the top to use short
	;jumps
	Found0_Pos:
		xor eax, eax
		inc eax
		pop ebx
		ret

	Found0_Neg:
		xor eax, eax
		dec eax
		pop ebx
		ret

	;we found a null, mask out all the bytes after it so we don't check extra
	;junk
	Found0_1:
		mov ebx, [ecx]
		and eax, 0000000FFh
		and ebx, 0000000FFh
		cmp eax, ebx

		je Found0_Ret
		jb Found0_Neg
		jg Found0_Pos

	Found0_2:
		mov ebx, [ecx]
		and eax, 00000FFFFh
		and ebx, 00000FFFFh

		xchg ah, al
		xchg bh, bl

		cmp eax, ebx
		je Found0_Ret
		jb Found0_Neg
		jg Found0_Pos

	Found0_3:
		mov ebx, [ecx]
		and eax, 000FFFFFFh
		and ebx, 000FFFFFFh

	StrCmpLoop_End:
		bswap eax
		bswap ebx

		cmp eax, ebx
		jg Found0_Pos
		jb Found0_Neg

	Found0_Ret:
		xor eax, eax
		pop ebx
		ret

Internal_ASM_strcmp endp

END