// File: /workspace/github_c_makefile_star2_O3/DavidSM64[P]DKR-Decompressor/GECompression.cpp
// Function: GECompression::OutputDecompressedBuffer(int&, int&)
unsigned char* GECompression::OutputDecompressedBuffer(int& fileSize, int& compressedSize)
{
	compressedSize = 0;
	if ((compressedBuffer == NULL) || (compressedBufferSize < 3))
		return NULL;


	if ((((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x1172) && (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x1173) && (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x68DE)&& (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x789C) && (((compressedBuffer[0] << 8) | compressedBuffer[1]) != 0x78DA) && (((compressedBuffer[0] << 24) | (compressedBuffer[1]<<16) | (compressedBuffer[2]<<8) | (compressedBuffer[3])) != 0x1F8B0800) && (((compressedBuffer[0] << 24) | (compressedBuffer[1]<<16) | (compressedBuffer[2]<<8) | (compressedBuffer[3])) != 0x1F8B0808) && (game != BLASTCORPS) && (game != BANJOTOOIE) && (game != CONKER)  && (game != TOPGEARRALLY) && (game != JFG) && (game != DKR) && (game != JFGKIOSK) && (game != MICKEYSPEEDWAY) && (game != ZLB))
	{
		//MessageBox(NULL, "Not 1172/1173/1F8B0800/1F8B0808 Compressed", "Error", NULL);
        std::cout << "Error: Not 1172/1173/1F8B0800/1F8B0808 Compressed" << std::endl;
		return NULL;
	}

	bitsCache = 0;
	bitsRemain = 0;
	if ((game == GOLDENEYE) || (game == KILLERINSTINCT) || (game == MILO) || (game == STUNTRACER64) || (game == RESIDENTEVIL2))
		bytesIndex = 2;
	else if (game == PD)
		bytesIndex = 5;
	else if (game == BANJOKAZOOIE)
		bytesIndex = 6;
	else if ((game == DONKEYKONG64) || (game == DONKEYKONG64KIOSK) || (game == BLASTCORPS))
		bytesIndex = 0xA;
	else if ((game == BANJOTOOIE))
		bytesIndex = 0x2;
	else if (game == CONKER)
		bytesIndex = 4;
	else if (game == TOPGEARRALLY)
		bytesIndex = 0xE;
	else if ((game == JFG) || (game == JFGKIOSK) || (game == DKR) || (game == MICKEYSPEEDWAY))
		bytesIndex = 0x5;
	else if (game == ZLB)
		bytesIndex = 0x12;


	if (((game == DONKEYKONG64) || (game == DONKEYKONG64KIOSK) || (game == BLASTCORPS)) && (((compressedBuffer[0] << 24) | (compressedBuffer[1]<<16) | (compressedBuffer[2]<<8) | (compressedBuffer[3])) == 0x1F8B0808))
	{
		while (compressedBuffer[bytesIndex] != 0)
			bytesIndex++;
		bytesIndex++;
	}
	unpackTableIndex = 0;
	for (int x = 0; x < 0xFFFF; x++)
	{
		unpackTable[x].bits = 0;
		unpackTable[x].flags = 0;
		unpackTable[x].nextIndex = 0;
		unpackTable[x].wordValue = 0;
	}

	unsigned char* returnBuffer;
	returnBuffer = new unsigned char[maxByteSize];


	bool done = false;
	unsigned char compressionType;
	fileSize = 0;

	iterationCounter = 0;

	do
	{
		if (iterationCounter > 268435455)
		{
			fileSize = 0;
			if (returnBuffer != NULL)
				delete [] returnBuffer;
			return NULL;
		}
		iterationCounter++;
		done = GetNBits(1);
		if (bytesIndex >= maxByteSize)
		{
			fileSize = 0;
			if (returnBuffer != NULL)
				delete [] returnBuffer;
			return NULL;
		}
		compressionType = GetNBits(2);
		if (compressionType == 0)
		{
			if (!UncompressType0(returnBuffer, fileSize))
			{
				fileSize = 0;
				if (returnBuffer != NULL)
					delete [] returnBuffer;
				return NULL;
			}
		}
		else if (compressionType == 1)
		{
			if (!UncompressType1(returnBuffer, fileSize))
			{
				fileSize = 0;
				if (returnBuffer != NULL)
					delete [] returnBuffer;
				return NULL;
			}
		}
		else if (compressionType == 2)
		{
			if (!UncompressType2(returnBuffer, fileSize))
			{
				fileSize = 0;
				if (returnBuffer != NULL)
					delete [] returnBuffer;
				return NULL;
			}
		}
		else
		{
			fileSize = 0;
				if (returnBuffer != NULL)
					delete [] returnBuffer;
				return NULL;
		}
	} while (done != 1);

	compressedSize = bytesIndex;
	return returnBuffer;	
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl $0x0, (%rdx)
movq 0x50(%rdi), %rax
xorl %r12d, %r12d
testq %rax, %rax
je 0x3bb3
movq %rdi, %r15
cmpl $0x3, 0x58(%rdi)
jl 0x3bb3
movq %rdx, %r14
movq %rsi, %rbx
movzbl (%rax), %edx
movl %edx, %esi
shll $0x8, %esi
movzbl 0x1(%rax), %ecx
orl %ecx, %esi
cmpl $0x789b, %esi           # imm = 0x789B
jg 0x3a02
leal -0x1172(%rsi), %r8d
movq %r15, %rdi
cmpl $0x2, %r8d
jb 0x3a41
movq %r15, %rdi
cmpl $0x68de, %esi           # imm = 0x68DE
je 0x3a41
jmp 0x3a18
movq %r15, %rdi
cmpl $0x789c, %esi           # imm = 0x789C
je 0x3a41
movq %r15, %rdi
cmpl $0x78da, %esi           # imm = 0x78DA
je 0x3a41
shll $0x18, %edx
shll $0x10, %ecx
orl %edx, %ecx
movzbl 0x2(%rax), %edx
shll $0x8, %edx
orl %ecx, %edx
movzbl 0x3(%rax), %ecx
orl %edx, %ecx
orl $0x8, %ecx
movq %r15, %rdi
cmpl $0x1f8b0808, %ecx       # imm = 0x1F8B0808
jne 0x3bc5
movl (%rdi), %ecx
movq $0x0, 0x38(%r15)
movl $0x0, 0x40(%r15)
cmpq $0x12, %rcx
ja 0x3ac3
leaq 0x3770(%rip), %rdx      # 0x71d0
movslq (%rdx,%rcx,4), %rsi
addq %rdx, %rsi
jmpq *%rsi
movl $0x2, %edx
jmp 0x3a7c
movl $0x5, %edx
jmp 0x3a7c
movl $0xa, %edx
movq %rdx, 0x48(%r15)
cmpl $0x7, %ecx
ja 0x3ac3
movl $0xb0, %edx
btl %ecx, %edx
jae 0x3ac3
movl (%rax), %ecx
bswapl %ecx
cmpl $0x1f8b0808, %ecx       # imm = 0x1F8B0808
jne 0x3ac3
movq 0x48(%r15), %rcx
cmpb $0x0, (%rax,%rcx)
je 0x3ab9
leaq 0x1(%rcx), %rdx
movq %rdx, 0x48(%r15)
cmpb $0x0, 0x1(%rax,%rcx)
movq %rdx, %rcx
jne 0x3aa5
jmp 0x3abc
movq %rcx, %rdx
incq %rdx
movq %rdx, 0x48(%r15)
movl $0x0, 0x30(%r15)
movq 0x28(%r15), %rax
movl $0x10, %ecx
xorl %edx, %edx
movq %rdx, -0x10(%rax,%rcx)
movb $0x0, -0x8(%rax,%rcx)
movl $0x0, -0x4(%rax,%rcx)
movq %rdx, (%rax,%rcx)
addq $0x18, %rcx
cmpq $0x17fff8, %rcx         # imm = 0x17FFF8
jne 0x3ad6
movl $0x800000, %edi         # imm = 0x800000
callq 0x2030
movq %rax, %r12
movl $0x0, (%rbx)
xorl %eax, %eax
incq %rax
movq %rax, 0x80(%r15)
movq %r15, %rdi
movl $0x1, %esi
callq 0x38bc
cmpq $0x800000, 0x48(%r15)   # imm = 0x800000
jae 0x3b99
movq %rax, %r13
movq %r15, %rdi
movl $0x2, %esi
callq 0x38bc
cmpb $0x2, %al
je 0x3b6f
movzbl %al, %eax
cmpl $0x1, %eax
je 0x3b5f
testl %eax, %eax
jne 0x3b99
movq %r15, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x3c62
jmp 0x3b7d
movq %r15, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x3d2c
jmp 0x3b7d
movq %r15, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x3dd6
testb %al, %al
je 0x3b99
testq %r13, %r13
jne 0x3bac
movq 0x80(%r15), %rax
cmpq $0x10000000, %rax       # imm = 0x10000000
jb 0x3b0e
movl $0x0, (%rbx)
movq %r12, %rdi
callq 0x21e0
xorl %r12d, %r12d
jmp 0x3bb3
movl 0x48(%r15), %eax
movl %eax, (%r14)
movq %r12, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl (%r15), %ecx
addl $-0x5, %ecx
cmpl $0xd, %ecx
jae 0x3c3a
movl $0x13db, %edx           # imm = 0x13DB
btl %ecx, %edx
jae 0x3c3a
movl %ecx, %ecx
leaq 0x3659(%rip), %rdx      # 0x723c
leaq (%rdx,%rcx,4), %rdi
jmp 0x3a41
movq $0xe, 0x48(%r15)
jmp 0x3ac3
movq $0x4, 0x48(%r15)
jmp 0x3ac3
movq $0x6, 0x48(%r15)
jmp 0x3ac3
movq $0x12, 0x48(%r15)
jmp 0x3ac3
movq $0x5, 0x48(%r15)
jmp 0x3ac3
movq $0x2, 0x48(%r15)
jmp 0x3ac3
movq 0x6397(%rip), %rbx      # 0x9fd8
leaq 0x3628(%rip), %rsi      # 0x7270
movl $0x31, %edx
movq %rbx, %rdi
callq 0x21c0
movq %rbx, %rdi
callq 0x20d0
jmp 0x3ba7