// File: /workspace/github_c_makefile_star2_O2/DavidSM64[P]DKR-Decompressor/GECompression.cpp
// Function: GECompression::DecompressBasedOnTable(int, int, int, int, unsigned char*, int&)
bool GECompression::DecompressBasedOnTable(int startIndex1, int startIndex2, int bitLen1, int bitLen2, unsigned char* returnBuffer, int& fileSize)
{
	unsigned long index = 0;
	bool exitFlag = 1;

	try
	{

	while (exitFlag)
	{

		if (iterationCounter > 268435455)
		{
			fileSize = 0;
			return false;
		}
		iterationCounter++;

		if (bytesIndex >= maxByteSize)
		{
			fileSize = 0;
			return false;
		}
		index = GetNBitsAndPreserve(bitLen1);
		if ((startIndex1 + index) > 0xFFFF)
		{
			fileSize = 0;
			return false;
		}
		tableEntry entry = unpackTable[startIndex1 + index];

		while (entry.flags > 0x10)
		{
			if (iterationCounter > 268435455)
			{
				fileSize = 0;
				return false;
			}
			iterationCounter++;

			if (bytesIndex >= maxByteSize)
			{
				fileSize = 0;
				return false;
			}
			GetNBits(entry.bits); // discard
			index = GetNBitsAndPreserve(entry.flags-0x10);
			if ((entry.nextIndex+index) > 0xFFFF)
			{
				fileSize = 0;
				return false;
			}
			entry = unpackTable[entry.nextIndex+index];
		}
		if (bytesIndex >= maxByteSize)
		{
			fileSize = 0;
			return false;
		}
		GetNBits(entry.bits); // discard
		
		if (entry.flags==0x10)
		{
			if (fileSize >= maxByteSize)
			{
				fileSize = 0;
				return false;
			}
			returnBuffer[fileSize] = entry.wordValue;
			fileSize++;
		}
		else if (entry.flags < 0xf)
		{
			unsigned long copyLen = entry.wordValue + GetNBits(entry.flags);
			unsigned long index2 = GetNBitsAndPreserve(bitLen2);
			if ((startIndex2+index2) > 0xFFFF)
			{
				fileSize = 0;
				return false;
			}
			tableEntry entry2 = unpackTable[startIndex2+index2];
			while (entry2.flags>0x10)
			{

				if (iterationCounter > 268435455)
				{
					fileSize = 0;
					return false;
				}
				iterationCounter++;

				if (bytesIndex >= maxByteSize)
				{
					fileSize = 0;
					return false;
				}
				GetNBits(entry2.bits); // discard
				index2 = GetNBitsAndPreserve(entry2.flags-0x10);
				if ((entry2.nextIndex+index2) > 0xFFFF)
				{
					fileSize = 0;
					return false;
				}
				entry2 = unpackTable[entry2.nextIndex+index2];
			}
			if (bytesIndex >= maxByteSize)
			{
				fileSize = 0;
				return false;
			}
			GetNBits(entry2.bits); // discard

			unsigned long endOffset1 = entry2.wordValue;
			unsigned long endOffset2 = GetNBits(entry2.flags);
			unsigned long start = fileSize-endOffset1-endOffset2;
			unsigned long end = start + copyLen;
			for (int x = start; x < end; x++)
			{
				if ((((signed long) start) < 0) || ((((signed long) end) < 0)) || ((start > maxByteSize)) || ((end > maxByteSize)))
				{
					fileSize = 0;
					return false;
				}
				returnBuffer[fileSize] = returnBuffer[x];
				fileSize++;
			}
		}
		else
			exitFlag = 0;
	}

	} catch (...)
	{
		return false;
	}
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %r9, -0x40(%rbp)
movl %r8d, -0x2c(%rbp)
movl %ecx, -0x30(%rbp)
movq %rdi, %r12
movslq %esi, %rbx
movslq %edx, %rax
movq %rax, -0x48(%rbp)
movb $0x1, %al
movl %eax, %r13d
testb $0x1, %al
je 0x4675
movq 0x80(%r12), %rax
cmpq $0xfffffff, %rax        # imm = 0xFFFFFFF
ja 0x466e
incq %rax
movq %rax, 0x80(%r12)
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x466e
movq %r12, %rdi
movl -0x30(%rbp), %esi
callq 0x359e
addq %rbx, %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x466e
movq 0x28(%r12), %rcx
imulq $0x18, %rax, %rax
movq (%rcx,%rax), %rsi
movzbl 0x8(%rcx,%rax), %r14d
cmpl $0x11, %r14d
jb 0x44df
movq 0x80(%r12), %rdx
cmpq $0xfffffff, %rdx        # imm = 0xFFFFFFF
ja 0x466e
movslq 0xc(%rcx,%rax), %r15
incq %rdx
movq %rdx, 0x80(%r12)
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x466e
movq %r12, %rdi
callq 0x3530
addl $-0x10, %r14d
movq %r12, %rdi
movl %r14d, %esi
callq 0x359e
addq %r15, %rax
jmp 0x446a
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x466e
movq 0x10(%rcx,%rax), %r15
movq %r12, %rdi
callq 0x3530
cmpl $0x10, %r14d
je 0x45b7
xorl %eax, %eax
cmpb $0xe, %r14b
ja 0x4423
movq %r12, %rdi
movl %r14d, %esi
callq 0x3530
movq %rax, -0x38(%rbp)
movq %r12, %rdi
movl -0x2c(%rbp), %esi
callq 0x359e
addq -0x48(%rbp), %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
ja 0x466e
addq %r15, -0x38(%rbp)
movq 0x28(%r12), %rcx
imulq $0x18, %rax, %rax
movq (%rcx,%rax), %rsi
movzbl 0x8(%rcx,%rax), %r14d
cmpl $0x11, %r14d
jb 0x45dd
movq 0x80(%r12), %rdx
cmpq $0xfffffff, %rdx        # imm = 0xFFFFFFF
ja 0x466e
movslq 0xc(%rcx,%rax), %r15
incq %rdx
movq %rdx, 0x80(%r12)
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x466e
movq %r12, %rdi
callq 0x3530
addl $-0x10, %r14d
movq %r12, %rdi
movl %r14d, %esi
callq 0x359e
addq %r15, %rax
cmpq $0xffff, %rax           # imm = 0xFFFF
jbe 0x453f
jmp 0x466e
movq 0x10(%rbp), %rax
movslq (%rax), %rax
cmpq $0x7fffff, %rax         # imm = 0x7FFFFF
jg 0x466e
movq -0x40(%rbp), %rcx
movb %r15b, (%rcx,%rax)
movq 0x10(%rbp), %rax
incl (%rax)
jmp 0x4421
cmpq $0x7fffff, 0x48(%r12)   # imm = 0x7FFFFF
ja 0x466e
movq 0x10(%rcx,%rax), %r15
movq %r12, %rdi
callq 0x3530
movq %r12, %rdi
movl %r14d, %esi
callq 0x3530
movq 0x10(%rbp), %rcx
movslq (%rcx), %rcx
addq %r15, %rax
movq %rcx, %rdx
subq %rax, %rdx
movq -0x38(%rbp), %r8
addq %rdx, %r8
movq %r8, %rax
orq %rdx, %rax
sets %sil
movl $0x800001, %eax         # imm = 0x800001
cmpq %rax, %rdx
setae %dil
movq %r8, %r9
cmpq %rax, %r8
setae %al
orb %dil, %al
orb %sil, %al
movslq %edx, %rdx
cmpq %rdx, %r9
jbe 0x4421
testb %al, %al
jne 0x466e
movq -0x40(%rbp), %rdi
movb (%rdi,%rdx), %sil
movslq %ecx, %rcx
movb %sil, (%rdi,%rcx)
movq 0x10(%rbp), %rsi
movl (%rsi), %ecx
incl %ecx
movl %ecx, (%rsi)
incq %rdx
jmp 0x4643
movq 0x10(%rbp), %rax
andl $0x0, (%rax)
notb %r13b
andb $0x1, %r13b
movl %r13d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop