// File: /workspace/github_cpp_makefile_star2_O2/Alcaro[P]bridges/arlib/zip.cpp
// Function: zip::pack() const
array<uint8_t> zip::pack() const
{
	array<uint8_t> ret;
	
	array<size_t> headerstarts;
	for (size_t i=0;i<filenames.size();i++)
	{
		headerstarts.append(ret.size());
		
		const file& f = filedat[i];
		locfhead h = {
			/*signature*/   locfhead::signature_expected,
			/*vermin*/      fileminver(f), // also contains host OS, but not important. and even if it was, pointless field
			/*bitflags*/    strascii(filenames[i]) ? 0 : 1<<11, // UTF-8 filenames
			/*compmethod*/  f.method,
			/*modtime*/     //merged
			/*moddate*/     f.dosdate,
			/*crc32*/       f.crc32,
			/*size_comp*/   f.data.size(),
			/*size_decomp*/ f.decomplen,
			/*len_fname*/   filenames[i].length(),
			/*len_exfield*/ 0,
		};
		arrayview<uint8_t> hb((uint8_t*)&h, sizeof(h));
		ret += hb;
		ret += filenames[i].bytes();
		ret += f.data;
	}
	
	size_t cdrstart = ret.size();
	for (size_t i=0;i<filenames.size();i++)
	{
		const file& f = filedat[i];
		centdirrec cdr = {
			/*signature*/    centdirrec::signature_expected,
			/*verused*/      63, // I don't think anything cares about this, just use latest
			/*vermin*/       fileminver(f),
			/*bitflags*/     strascii(filenames[i]) ? 0 : 1<<11,
			/*compmethod*/   f.method,
			/*modtime*/      //merged
			/*moddate*/      f.dosdate,
			/*crc32*/        f.crc32,
			/*size_comp*/    f.data.size(),
			/*size_decomp*/  f.decomplen,
			/*len_fname*/    filenames[i].length(),
			/*len_exfield*/  0,
			/*len_fcomment*/ 0,
			/*disknr*/       0,
			/*attr_int*/     0,
			// the ZIP specification defines the low byte of external attributes to be the MS-DOS directory attribute byte
			// aka https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
			// upper three bytes are undefined and contradictorily used
			// Windows Explorer uses the lower 16 bits as is, probably all 32 but hard to test
			// Unix tools usually put the permission bits, as well as __S_IFDIR, in upper 16 (0o644 << 16)
			// at least one OSX tool sometimes sets the 0x4000 flag for some unknown purpose (which Windows misreads as F_A_ENCRYPTED)
			// only the is-directory flag makes sense in a zip, others should not be present in a distributable archive
			/*attr_ext*/     filenames[i].endswith("/") ? 0x10 : 0x00,
			/*header_start*/ headerstarts[i],
		};
		arrayview<uint8_t> cdrb((uint8_t*)&cdr, sizeof(cdr));
		ret += cdrb;
		ret += filenames[i].bytes();
	}
	size_t cdrend = ret.size();
	
	endofcdr eod = {
		/*signature*/         endofcdr::signature_expected,
		/*diskid_this*/       0,
		/*diskid_cdrst*/      0,
		/*numfiles_thisdisk*/ filenames.size(),
		/*numfiles*/          filenames.size(),
		/*cdrsize*/           cdrend-cdrstart,
		/*cdrstart_fromdisk*/ cdrstart,
		/*zipcommentlen*/     0,
	};
	arrayview<uint8_t> eodb((uint8_t*)&eod, sizeof(eod));
	ret += eodb;
	
	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, %r14
movq %rdi, %rbx
pxor %xmm0, %xmm0
movdqu %xmm0, (%rdi)
leaq 0x40(%rsp), %rax
movdqa %xmm0, (%rax)
xorl %r15d, %r15d
movq %rsp, %r12
xorl %ecx, %ecx
movq %rdi, 0x38(%rsp)
movq 0x8(%r14), %rax
cmpq %rax, %rcx
jae 0x181cd
movq %rcx, 0x30(%rsp)
movq 0x8(%rbx), %rax
movq %rax, (%rsp)
leaq 0x40(%rsp), %rdi
movq %r12, %r13
movq %r12, %rsi
callq 0xdc3c
movq 0x10(%r14), %rbp
movl $0x4034b50, (%rsp)      # imm = 0x4034B50
movzwl 0x4(%rbp,%r15,2), %ebx
cmpw $0x8, %bx
pushq $0xa
popq %rax
pushq $0x14
popq %rcx
cmovel %ecx, %eax
movw %ax, 0x4(%rsp)
movq (%r14), %r12
movq (%r12,%r15), %rdi
movq 0x8(%r12,%r15), %rsi
callq 0x17df2
xorb $0x1, %al
movzbl %al, %eax
shll $0xb, %eax
movw %ax, 0x6(%rsp)
movw %bx, 0x8(%rsp)
movq 0x18(%rbp,%r15,2), %xmm0
pshufd $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movq %xmm0, 0xa(%rsp)
movl 0x10(%rbp,%r15,2), %eax
movl %eax, 0x12(%rsp)
movl (%rbp,%r15,2), %eax
movl %eax, 0x16(%rsp)
movzbl 0xf(%r12,%r15), %eax
testb %al, %al
js 0x1815d
xorl $0xf, %eax
jmp 0x18162
movl 0x8(%r12,%r15), %eax
movw %ax, 0x1a(%rsp)
andw $0x0, 0x1c(%rsp)
movq 0x38(%rsp), %rbx
movq %rbx, %rdi
movq %r13, %r12
movq %r13, %rsi
pushq $0x1e
popq %rdx
callq 0xbd94
movq (%r14), %rsi
movzbl 0xf(%rsi,%r15), %edx
testb %dl, %dl
js 0x18199
addq %r15, %rsi
xorq $0xf, %rdx
jmp 0x181a2
movl 0x8(%rsi,%r15), %edx
movq (%rsi,%r15), %rsi
movq %rbx, %rdi
callq 0xbd94
movq 0x8(%rbp,%r15,2), %rsi
movq 0x10(%rbp,%r15,2), %rdx
movq %rbx, %rdi
callq 0xbd94
movq 0x30(%rsp), %rcx
incq %rcx
addq $0x10, %r15
jmp 0x180ba
movq 0x8(%rbx), %rcx
movq %rcx, 0x50(%rsp)
xorl %r13d, %r13d
xorl %r15d, %r15d
cmpq %rax, %r15
jae 0x18306
movq %r15, 0x30(%rsp)
movq 0x10(%r14), %rbp
movl $0x2014b50, (%rsp)      # imm = 0x2014B50
movw $0x3f, 0x4(%rsp)
movzwl 0x4(%rbp,%r13,2), %ebx
cmpw $0x8, %bx
pushq $0xa
popq %rax
pushq $0x14
popq %rcx
cmovel %ecx, %eax
movw %ax, 0x6(%rsp)
movq (%r14), %r12
leaq (%r12,%r13), %r15
movq (%r12,%r13), %rdi
movq 0x8(%r12,%r13), %rsi
callq 0x17df2
xorb $0x1, %al
movzbl %al, %eax
shll $0xb, %eax
movw %ax, 0x8(%rsp)
movw %bx, 0xa(%rsp)
movq 0x18(%rbp,%r13,2), %xmm0
pshufd $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movq %xmm0, 0xc(%rsp)
movl 0x10(%rbp,%r13,2), %eax
movl %eax, 0x14(%rsp)
movl (%rbp,%r13,2), %eax
movl %eax, 0x18(%rsp)
movzbl 0xf(%r12,%r13), %eax
testb %al, %al
js 0x1826e
xorl $0xf, %eax
jmp 0x18272
movl 0x8(%r15), %eax
movq 0x38(%rsp), %rbx
movw %ax, 0x1c(%rsp)
andq $0x0, 0x1e(%rsp)
leaq 0x58(%rsp), %rdi
leaq 0x10cd2(%rip), %rsi     # 0x28f60
callq 0x42ce
movq 0x58(%rsp), %rsi
movq 0x60(%rsp), %rdx
movq %r15, %rdi
callq 0x14a9e
movzbl %al, %eax
shll $0x4, %eax
movl %eax, 0x26(%rsp)
movq 0x40(%rsp), %rax
movq 0x30(%rsp), %r15
movl (%rax,%r15,8), %eax
movl %eax, 0x2a(%rsp)
movq %rbx, %rdi
movq %rsp, %rsi
pushq $0x2e
popq %rdx
callq 0xbd94
movq (%r14), %rsi
movzbl 0xf(%rsi,%r13), %edx
testb %dl, %dl
js 0x182e5
addq %r13, %rsi
xorq $0xf, %rdx
jmp 0x182ee
movl 0x8(%rsi,%r13), %edx
movq (%rsi,%r13), %rsi
movq %rbx, %rdi
callq 0xbd94
incq %r15
movq 0x8(%r14), %rax
addq $0x10, %r13
jmp 0x181dc
movl 0x8(%rbx), %ecx
movq %rsp, %rsi
movq $0x6054b50, (%rsi)      # imm = 0x6054B50
movw %ax, 0x8(%rsi)
movw %ax, 0xa(%rsi)
movq 0x50(%rsp), %rax
subl %eax, %ecx
movl %ecx, 0xc(%rsi)
movl %eax, 0x10(%rsi)
andw $0x0, 0x14(%rsi)
pushq $0x16
popq %rdx
movq %rbx, %rdi
callq 0xbd94
movq 0x40(%rsp), %rdi
callq 0x3430
movq %rbx, %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq