// File: /workspace/github_c_makefile_star2_O2/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
subq $0x18, %rsp
movq %rsi, -0x30(%rbp)
andl $0x0, (%rdx)
movq 0x50(%rdi), %rax
xorl %r12d, %r12d
testq %rax, %rax
je 0x385a
movq %rdi, %r15
cmpl $0x3, 0x58(%rdi)
jl 0x385a
movzbl (%rax), %r9d
movl %r9d, %esi
shll $0x8, %esi
movzbl 0x1(%rax), %ecx
leal (%rsi,%rcx), %r8d
addl $0xffffee8e, %r8d       # imm = 0xFFFFEE8E
movq %r15, %rdi
cmpl $0x2, %r8d
jb 0x36a1
orl %ecx, %esi
movq %r15, %rdi
cmpl $0x68de, %esi           # imm = 0x68DE
je 0x36a1
movq %r15, %rdi
cmpl $0x789c, %esi           # imm = 0x789C
je 0x36a1
movq %r15, %rdi
cmpl $0x78da, %esi           # imm = 0x78DA
je 0x36a1
shll $0x18, %r9d
shll $0x10, %ecx
orl %r9d, %ecx
movzbl 0x2(%rax), %esi
shll $0x8, %esi
orl %ecx, %esi
movzbl 0x3(%rax), %ecx
orl %esi, %ecx
orl $0x8, %ecx
movq %r15, %rdi
cmpl $0x1f8b0808, %ecx       # imm = 0x1F8B0808
jne 0x3709
movl (%rdi), %ecx
andq $0x0, 0x38(%r15)
andl $0x0, 0x40(%r15)
cmpq $0x12, %rcx
ja 0x3753
leaq 0x3b12(%rip), %rdi      # 0x71d0
movslq (%rdi,%rcx,4), %rsi
addq %rdi, %rsi
jmpq *%rsi
pushq $0x2
jmp 0x36d1
pushq $0x5
jmp 0x36d1
pushq $0xa
popq %rsi
movq %rsi, 0x48(%r15)
cmpl $0x7, %ecx
ja 0x3753
movl $0xb0, %esi
btl %ecx, %esi
jae 0x3753
movl (%rax), %ecx
bswapl %ecx
cmpl $0x1f8b0808, %ecx       # imm = 0x1F8B0808
jne 0x3753
movq 0x48(%r15), %rcx
incq %rcx
cmpb $0x0, -0x1(%rax,%rcx)
movq %rcx, 0x48(%r15)
leaq 0x1(%rcx), %rcx
jne 0x36f8
jmp 0x3753
movl (%r15), %ecx
addl $-0x5, %ecx
cmpl $0xd, %ecx
jae 0x386c
movl $0x13db, %esi           # imm = 0x13DB
btl %ecx, %esi
jae 0x386c
movl %ecx, %ecx
leaq 0x3b0d(%rip), %rsi      # 0x723c
leaq (%rsi,%rcx,4), %rdi
jmp 0x36a1
pushq $0xe
jmp 0x374e
pushq $0x4
jmp 0x374e
pushq $0x6
jmp 0x374e
pushq $0x12
jmp 0x374e
pushq $0x5
jmp 0x374e
pushq $0x2
popq %rax
movq %rax, 0x48(%r15)
andl $0x0, 0x30(%r15)
movq 0x28(%r15), %rax
pushq $0x10
popq %rcx
cmpq $0x17fff8, %rcx         # imm = 0x17FFF8
je 0x3783
andq $0x0, -0x10(%rax,%rcx)
movb $0x0, -0x8(%rax,%rcx)
andl $0x0, -0x4(%rax,%rcx)
andq $0x0, (%rax,%rcx)
addq $0x18, %rcx
jmp 0x375f
movq %rdx, -0x38(%rbp)
movl $0x800000, %edi         # imm = 0x800000
callq 0x2030
movq -0x30(%rbp), %rcx
andl $0x0, (%rcx)
andq $0x0, 0x80(%r15)
movq %rax, %r12
xorl %eax, %eax
pushq $0x1
popq %r13
pushq $0x2
popq %r14
cmpq $0x10000000, %rax       # imm = 0x10000000
jae 0x383c
incq %rax
movq %rax, 0x80(%r15)
movq %r15, %rdi
movl %r13d, %esi
callq 0x3530
cmpq $0x800000, 0x48(%r15)   # imm = 0x800000
jae 0x383c
movq %rax, %rbx
movq %r15, %rdi
movl %r14d, %esi
callq 0x3530
cmpb $0x2, %al
je 0x3818
movzbl %al, %eax
cmpl $0x1, %eax
je 0x3807
testl %eax, %eax
jne 0x383c
movq %r15, %rdi
movq %r12, %rsi
movq -0x30(%rbp), %rdx
callq 0x388a
jmp 0x3827
movq %r15, %rdi
movq %r12, %rsi
movq -0x30(%rbp), %rdx
callq 0x3928
jmp 0x3827
movq %r15, %rdi
movq %r12, %rsi
movq -0x30(%rbp), %rdx
callq 0x39ca
testb %al, %al
je 0x383c
testq %rbx, %rbx
jne 0x3850
movq 0x80(%r15), %rax
jmp 0x37ad
movq -0x30(%rbp), %rax
andl $0x0, (%rax)
movq %r12, %rdi
callq 0x21c0
xorl %r12d, %r12d
jmp 0x385a
movl 0x48(%r15), %eax
movq -0x38(%rbp), %rcx
movl %eax, (%rcx)
movq %r12, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x675d(%rip), %rdi      # 0x9fd0
leaq 0x39f6(%rip), %rsi      # 0x7270
callq 0x2160
movq %rax, %rdi
callq 0x20d0
jmp 0x384b
nop