// File: /workspace/github_cpp_makefile_star2_O3/soybin[P]idyll/src/lib/TinyPngOut.cpp
// Function: TinyPngOut::write(unsigned char const*, unsigned long)
void TinyPngOut::write(const uint8_t pixels[], size_t count) {
	if (count > SIZE_MAX / 3)
		throw std::length_error("Invalid argument");
	count *= 3;  // Convert pixel count to byte count
	while (count > 0) {
		if (pixels == nullptr)
			throw std::invalid_argument("Null pointer");
		if (positionY >= height)
			throw std::logic_error("All image pixels already written");
		
		if (deflateFilled == 0) {  // Start DEFLATE block
			uint16_t size = DEFLATE_MAX_BLOCK_SIZE;
			if (uncompRemain < size)
				size = static_cast<uint16_t>(uncompRemain);
			const uint8_t header[] = {  // 5 bytes long
				static_cast<uint8_t>(uncompRemain <= DEFLATE_MAX_BLOCK_SIZE ? 1 : 0),
				static_cast<uint8_t>(size >> 0),
				static_cast<uint8_t>(size >> 8),
				static_cast<uint8_t>((size >> 0) ^ 0xFF),
				static_cast<uint8_t>((size >> 8) ^ 0xFF),
			};
			write(header);
			crc32(header, sizeof(header) / sizeof(header[0]));
		}
		assert(positionX < lineSize && deflateFilled < DEFLATE_MAX_BLOCK_SIZE);
		
		if (positionX == 0) {  // Beginning of line - write filter method byte
			uint8_t b[] = {0};
			write(b);
			crc32(b, 1);
			adler32(b, 1);
			positionX++;
			uncompRemain--;
			deflateFilled++;
			
		} else {  // Write some pixel bytes for current line
			uint16_t n = DEFLATE_MAX_BLOCK_SIZE - deflateFilled;
			if (lineSize - positionX < n)
				n = static_cast<uint16_t>(lineSize - positionX);
			if (count < n)
				n = static_cast<uint16_t>(count);
			if (static_cast<std::make_unsigned<std::streamsize>::type>(std::numeric_limits<std::streamsize>::max()) < std::numeric_limits<decltype(n)>::max())
				n = std::min(n, static_cast<decltype(n)>(std::numeric_limits<std::streamsize>::max()));
			assert(n > 0);
			output.write(reinterpret_cast<const char*>(pixels), static_cast<std::streamsize>(n));
			
			// Update checksums
			crc32(pixels, n);
			adler32(pixels, n);
			
			// Increment positions
			count -= n;
			pixels += n;
			positionX += n;
			uncompRemain -= n;
			deflateFilled += n;
		}
		
		if (deflateFilled >= DEFLATE_MAX_BLOCK_SIZE)
			deflateFilled = 0;  // End current block
		
		if (positionX == lineSize) {  // Increment line
			positionX = 0;
			positionY++;
			if (positionY == height) {  // Reached end of pixels
				uint8_t footer[] = {  // 20 bytes long
					0, 0, 0, 0,  // DEFLATE Adler-32 placeholder
					0, 0, 0, 0,  // IDAT CRC-32 placeholder
					// IEND chunk
					0x00, 0x00, 0x00, 0x00,
					0x49, 0x45, 0x4E, 0x44,
					0xAE, 0x42, 0x60, 0x82,
				};
				putBigUint32(adler, &footer[0]);
				crc32(&footer[0], 4);
				putBigUint32(crc, &footer[4]);
				write(footer);
			}
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movabsq $0x5555555555555556, %rax # imm = 0x5555555555555556
cmpq %rax, %rdx
jae 0xd3a7
testq %rdx, %rdx
je 0xd2fc
movq %rsi, %rbx
movq %rdi, %r14
leaq (%rdx,%rdx,2), %rax
movq %rax, -0x48(%rbp)
movl $0x80078071, %r15d      # imm = 0x80078071
testq %rbx, %rbx
je 0xd356
movl 0x1c(%r14), %eax
cmpl 0x4(%r14), %eax
jae 0xd32a
cmpw $0x0, 0x24(%r14)
jne 0xd0f5
movl 0x20(%r14), %eax
movl $0xffff, %ecx           # imm = 0xFFFF
cmpl %ecx, %eax
cmovbl %eax, %ecx
cmpl $0x10000, %eax          # imm = 0x10000
setb -0x40(%rbp)
movb %cl, -0x3f(%rbp)
movl %ecx, %eax
shrl $0x8, %eax
movb %al, -0x3e(%rbp)
notb %cl
movb %cl, -0x3d(%rbp)
notb %al
movb %al, -0x3c(%rbp)
movq 0x10(%r14), %rdi
movl $0x5, %edx
leaq -0x40(%rbp), %r12
movq %r12, %rsi
callq 0x3350
movl $0x5, %edx
movq %r14, %rdi
movq %r12, %rsi
callq 0xcfec
movl 0x8(%r14), %eax
movl 0x18(%r14), %edx
subl %edx, %eax
jbe 0xd30b
movzwl 0x24(%r14), %ecx
cmpw $-0x1, %cx
je 0xd30b
testl %edx, %edx
je 0xd1d0
notl %ecx
movl %ecx, %edx
movl $0xffff, %esi           # imm = 0xFFFF
andl %esi, %edx
cmpl %edx, %eax
cmovbl %eax, %ecx
movl %ecx, %eax
andl %esi, %eax
movq -0x48(%rbp), %rdx
cmpq %rax, %rdx
movl %edx, %r13d
cmovael %ecx, %r13d
testw %r13w, %r13w
je 0xd388
movq 0x10(%r14), %rdi
movzwl %r13w, %r12d
movq %rbx, %rsi
movq %r12, %rdx
callq 0x3350
movq %r14, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0xcfec
movl 0x2c(%r14), %eax
movzwl %ax, %ecx
shrl $0x10, %eax
xorl %edx, %edx
movzbl (%rbx,%rdx), %esi
addl %ecx, %esi
movl %esi, %ecx
imulq %r15, %rsi
shrq $0x2f, %rsi
imull $0xfff1, %esi, %esi     # imm = 0xFFF1
subl %esi, %ecx
addl %ecx, %eax
movq %rax, %rsi
imulq %r15, %rsi
shrq $0x2f, %rsi
imull $0xfff1, %esi, %esi     # imm = 0xFFF1
subl %esi, %eax
incq %rdx
cmpq %rdx, %r12
jne 0xd175
shll $0x10, %eax
orl %ecx, %eax
movl %eax, 0x2c(%r14)
subq %r12, -0x48(%rbp)
movl 0x18(%r14), %ecx
addl %r12d, %ecx
movl %ecx, 0x18(%r14)
subl %r12d, 0x20(%r14)
addq %r12, %rbx
addw 0x24(%r14), %r13w
jmp 0xd247
movb $0x0, -0x40(%rbp)
movq 0x10(%r14), %rdi
movl $0x1, %edx
leaq -0x40(%rbp), %r12
movq %r12, %rsi
callq 0x3350
movl $0x1, %edx
movq %r14, %rdi
movq %r12, %rsi
callq 0xcfec
movl 0x2c(%r14), %eax
movzwl %ax, %ecx
shrl $0x10, %eax
movzbl -0x40(%rbp), %edx
addl %ecx, %edx
movl %edx, %ecx
subl $0xfff1, %ecx           # imm = 0xFFF1
cmovbl %edx, %ecx
addl %ecx, %eax
movq %rax, %rdx
imulq %r15, %rdx
shrq $0x2f, %rdx
imull $0xfff1, %edx, %edx     # imm = 0xFFF1
subl %edx, %eax
shll $0x10, %eax
orl %ecx, %eax
movl %eax, 0x2c(%r14)
movl 0x18(%r14), %ecx
movl 0x24(%r14), %r13d
incl %ecx
movl %ecx, 0x18(%r14)
decl 0x20(%r14)
incl %r13d
movw %r13w, 0x24(%r14)
cmpw $-0x1, %r13w
jne 0xd25a
movw $0x0, 0x24(%r14)
cmpl 0x8(%r14), %ecx
jne 0xd2f1
movl $0x0, 0x18(%r14)
movl 0x1c(%r14), %ecx
incl %ecx
movl %ecx, 0x1c(%r14)
cmpl 0x4(%r14), %ecx
jne 0xd2f1
movaps 0x1a6d(%rip), %xmm0     # 0xecf0
movaps %xmm0, -0x40(%rbp)
movl $0x826042ae, -0x30(%rbp) # imm = 0x826042AE
movl $0x18, %ecx
xorl %edx, %edx
movl %eax, %esi
shrl %cl, %esi
movb %sil, -0x40(%rbp,%rdx)
incq %rdx
addl $-0x8, %ecx
cmpq $0x4, %rdx
jne 0xd295
movl $0x4, %r12d
movl $0x4, %edx
movq %r14, %rdi
leaq -0x40(%rbp), %rsi
callq 0xcfec
movl 0x28(%r14), %eax
movl $0x18, %ecx
movl %eax, %edx
shrl %cl, %edx
movb %dl, -0x40(%rbp,%r12)
incq %r12
addl $-0x8, %ecx
cmpq $0x8, %r12
jne 0xd2ca
movq 0x10(%r14), %rdi
movl $0x14, %edx
leaq -0x40(%rbp), %rsi
callq 0x3350
cmpq $0x0, -0x48(%rbp)
jne 0xd085
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1922(%rip), %rdi      # 0xec34
leaq 0x195a(%rip), %rsi      # 0xec73
leaq 0x196a(%rip), %rcx      # 0xec8a
movl $0x7a, %edx
callq 0x31a0
movl $0x10, %edi
callq 0x3130
movq %rax, %r14
leaq 0x18d5(%rip), %rsi      # 0xec13
movq %rax, %rdi
callq 0x3380
movq 0x5c83(%rip), %rsi      # 0x12fd0
movq 0x5c54(%rip), %rdx      # 0x12fa8
jmp 0xd380
movl $0x10, %edi
callq 0x3130
movq %rax, %r14
leaq 0x189c(%rip), %rsi      # 0xec06
movq %rax, %rdi
callq 0x34f0
movq 0x5c5f(%rip), %rsi      # 0x12fd8
movq 0x5c38(%rip), %rdx      # 0x12fb8
movq %r14, %rdi
callq 0x3450
leaq 0x192b(%rip), %rdi      # 0xecba
leaq 0x18dd(%rip), %rsi      # 0xec73
leaq 0x18ed(%rip), %rcx      # 0xec8a
movl $0x8d, %edx
callq 0x31a0
movl $0x10, %edi
callq 0x3130
movq %rax, %r14
leaq 0x183a(%rip), %rsi      # 0xebf5
movq %rax, %rdi
callq 0x3330
movq 0x5bf6(%rip), %rsi      # 0x12fc0
movq 0x5bcf(%rip), %rdx      # 0x12fa0
jmp 0xd380
jmp 0xd3d7
jmp 0xd3d7
movq %rax, %rbx
movq %r14, %rdi
callq 0x31e0
movq %rbx, %rdi
callq 0x3490