// File: OpenFodder[P]SOS_Unpacker/capsimg/Core/BitBuffer.cpp
// Function: CBitBuffer::WriteBitWrap(unsigned char*, unsigned int, unsigned int, unsigned int, int)
void CBitBuffer::WriteBitWrap(uint8_t *buf, uint32_t bufwrap, uint32_t bitpos, uint32_t value, int bitcnt)
{
	// slow write mode if buffer would wrap around during writing, otherwise use fast write
	if (bitpos + bitcnt > bufwrap) {
		// slow mode; set/clear each bit affected and handle buffer wrap

		// bitfield has to be at least 1 bit wide, otherwise finished
		if (bitcnt <= 0)
			return;

		// read bitmask; use bit[bitcnt-1...0] as bitfield from value
		uint32_t rbit = 1 << (bitcnt - 1);

		// write bitmask
		uint32_t wbit = 1 << ((bitpos & 7) ^ 7);

		// write buffer position
		uint8_t *wpos = buf + (bitpos >> 3);

		// read data from buffer
		uint32_t data = *wpos;

		// process all bits
		while (rbit) {
			// set/clear current bit to be written according to the value of the bit selected by the read bitmask
			if (value & rbit)
				data |= wbit;
			else
				data &= ~wbit;

			// get next bit position to read and write
			rbit >>= 1;
			bitpos++;

			if (bitpos == bufwrap) {
				// buffer wraps, commit data
				bitpos = 0;
				*wpos = (uint8_t)data;

				// restart buffer from bit#7
				wpos = buf;
				wbit = 0x80;
				data = *wpos;
			} else {
				if (!(wbit >>= 1)) {
					// data complete, commit and get the next one
					*wpos = (uint8_t)data;
					wpos++;
					wbit = 0x80;
					data = *wpos;
				}
			}
		}

		// commit data
		*wpos = (uint8_t)data;
	} else {
		// fast mode; write at once
		WriteBit(buf, bitpos, value, bitcnt);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
movl %r8d, -0x18(%rbp)
movl -0x10(%rbp), %eax
addl -0x18(%rbp), %eax
cmpl -0xc(%rbp), %eax
jbe 0x4fbe
cmpl $0x0, -0x18(%rbp)
jg 0x4ec3
jmp 0x4fd0
movl -0x18(%rbp), %ecx
subl $0x1, %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, -0x1c(%rbp)
movl -0x10(%rbp), %ecx
andl $0x7, %ecx
xorl $0x7, %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movl -0x10(%rbp), %ecx
shrl $0x3, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x1c(%rbp)
je 0x4fb1
movl -0x14(%rbp), %eax
andl -0x1c(%rbp), %eax
cmpl $0x0, %eax
je 0x4f23
movl -0x20(%rbp), %eax
orl -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
jmp 0x4f2f
movl -0x20(%rbp), %eax
xorl $-0x1, %eax
andl -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl -0x1c(%rbp), %eax
shrl %eax
movl %eax, -0x1c(%rbp)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
movl -0x10(%rbp), %eax
cmpl -0xc(%rbp), %eax
jne 0x4f75
movl $0x0, -0x10(%rbp)
movl -0x2c(%rbp), %eax
movb %al, %cl
movq -0x28(%rbp), %rax
movb %cl, (%rax)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movl $0x80, -0x20(%rbp)
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x2c(%rbp)
jmp 0x4fac
movl -0x20(%rbp), %eax
shrl %eax
movl %eax, -0x20(%rbp)
cmpl $0x0, %eax
jne 0x4faa
movl -0x2c(%rbp), %eax
movb %al, %cl
movq -0x28(%rbp), %rax
movb %cl, (%rax)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
movl $0x80, -0x20(%rbp)
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x2c(%rbp)
jmp 0x4fac
jmp 0x4f03
movl -0x2c(%rbp), %eax
movb %al, %cl
movq -0x28(%rbp), %rax
movb %cl, (%rax)
jmp 0x4fd0
movq -0x8(%rbp), %rdi
movl -0x10(%rbp), %esi
movl -0x14(%rbp), %edx
movl -0x18(%rbp), %ecx
callq 0x4fe0
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)