// File: /workspace/github_c_makefile_star2_O2/jsummers[P]deark/src/fmtutil-advfile.c
// Function: de_advfile_run_applesd
static void de_advfile_run_applesd(deark *c, struct de_advfile *advf, int is_appledouble)
{
	de_ucstring *fname = NULL;
	struct de_advfile_cbparams *afp_main = NULL;
	struct de_advfile_cbparams *afp_rsrc = NULL;
	dbuf *outf = NULL;
	i64 cur_data_pos;
	size_t num_entries = 0;
	size_t k;
	char commentstr[80];
	size_t comment_strlen;
	struct applesd_entry entry_info[16];

	fname = ucstring_create(c);
	ucstring_append_ucstring(fname, advf->filename);
	if(fname->len<1) {
		ucstring_append_sz(fname, "_", DE_ENCODING_LATIN1);
	}
	if(is_appledouble) {
		// TODO: Consider using "._" prefix when writing to ZIP/tar
		ucstring_append_sz(fname, ".adf", DE_ENCODING_LATIN1);
	}
	else {
		ucstring_append_sz(fname, ".as", DE_ENCODING_LATIN1);
	}
	de_finfo_set_name_from_ucstring(c, advf->mainfork.fi, fname, advf->snflags);
	advf->mainfork.fi->original_filename_flag = advf->original_filename_flag;
	outf = dbuf_create_output_file(c, NULL, advf->mainfork.fi, advf->createflags);
	if(advf->enable_wbuffer) dbuf_enable_wbuffer(outf);

	if(is_appledouble) { // signature
		dbuf_writeu32be(outf, 0x00051607U);
	}
	else {
		dbuf_writeu32be(outf, 0x00051600U);
	}
	dbuf_writeu32be(outf, 0x00020000U); // version
	dbuf_write_zeroes(outf, 16); // filler

	// Decide what entries we will write, and in what order, and their data length.

	de_snprintf(commentstr, sizeof(commentstr), "Apple%s container generated by Deark",
		is_appledouble?"Double":"Single");
	comment_strlen = de_strlen(commentstr);

	if(advf->orig_filename) {
		entry_info[num_entries].id = SDID_REALNAME;
		entry_info[num_entries].len = (i64)advf->orig_filename_len;
		num_entries++;
	}

	entry_info[num_entries].id = SDID_COMMENT;
	entry_info[num_entries].len = (i64)comment_strlen;
	num_entries++;

	if(advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_CREATE].is_valid ||
		advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_MODIFY].is_valid ||
		advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_BACKUP].is_valid ||
		advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_ACCESS].is_valid)
	{
		entry_info[num_entries].id = SDID_FILEDATES;
		entry_info[num_entries].len = 16;
		num_entries++;
	}
	if((advf->has_typecode || advf->has_creatorcode || advf->has_finderflags) &&
		!advf->mainfork.fi->is_directory)
	{
		entry_info[num_entries].id = SDID_FINDERINFO;
		entry_info[num_entries].len = 32;
		num_entries++;
	}
	if(advf->rsrcfork.fork_exists) {
		entry_info[num_entries].id = SDID_RESOURCEFORK;
		entry_info[num_entries].len = advf->rsrcfork.fork_len;
		num_entries++;
	};
	if(advf->mainfork.fork_exists && !is_appledouble) {
		entry_info[num_entries].id = SDID_DATAFORK;
		entry_info[num_entries].len = advf->mainfork.fork_len;
		num_entries++;
	};

	dbuf_writeu16be(outf, (i64)num_entries);

	// Figure out where the each data element will be written.
	cur_data_pos = 26 + 12*(i64)num_entries;
	for(k=0; k<num_entries; k++) {
		entry_info[k].offset = cur_data_pos;
		cur_data_pos += entry_info[k].len;
	};

	// Write the element table
	for(k=0; k<num_entries; k++) {
		dbuf_writeu32be(outf, (i64)entry_info[k].id);
		if(entry_info[k].offset>0xffffffffLL || entry_info[k].len>0xffffffffLL) {
			de_err(c, "File too large to write to AppleSingle/AppleDouble format");
			goto done;
		}
		dbuf_writeu32be(outf, entry_info[k].offset);
		dbuf_writeu32be(outf, entry_info[k].len);
	}

	// Write the elements' data
	for(k=0; k<num_entries; k++) {
		switch(entry_info[k].id) {
		case SDID_DATAFORK:
			afp_main = de_malloc(c, sizeof(struct de_advfile_cbparams));
			afp_main->whattodo = DE_ADVFILE_WRITEMAIN;
			dbuf_set_writelistener(outf, advf->mainfork.writelistener_cb,
				advf->mainfork.userdata_for_writelistener);
			afp_main->outf = outf;
			if(advf->writefork_cbfn && advf->mainfork.fork_len>0) {
				advf->writefork_cbfn(c, advf, afp_main);
			}
			dbuf_set_writelistener(outf, NULL, NULL);
			break;

		case SDID_RESOURCEFORK:
			afp_rsrc = de_malloc(c, sizeof(struct de_advfile_cbparams));
			afp_rsrc->whattodo = DE_ADVFILE_WRITERSRC;
			dbuf_set_writelistener(outf, advf->rsrcfork.writelistener_cb,
				advf->rsrcfork.userdata_for_writelistener);
			afp_rsrc->outf = outf;
			if(advf->writefork_cbfn && advf->rsrcfork.fork_len>0) {
				advf->writefork_cbfn(c, advf, afp_rsrc);
			}
			dbuf_set_writelistener(outf, NULL, NULL);
			break;

		case SDID_REALNAME:
			// If you think this code might be wrong, first review the comments
			// in applesd.c regarding Pascal strings.
			dbuf_write(outf, advf->orig_filename, (i64)advf->orig_filename_len);
			break;

		case SDID_COMMENT:
			dbuf_write(outf, (const u8*)commentstr, (i64)comment_strlen);
			break;

		case SDID_FILEDATES:
			dbuf_writei32be(outf, timestamp_to_applesd_date(c, &advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_CREATE]));
			dbuf_writei32be(outf, timestamp_to_applesd_date(c, &advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_MODIFY]));
			dbuf_writei32be(outf, timestamp_to_applesd_date(c, &advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_BACKUP]));
			dbuf_writei32be(outf, timestamp_to_applesd_date(c, &advf->mainfork.fi->timestamp[DE_TIMESTAMPIDX_ACCESS]));
			break;

		case SDID_FINDERINFO:
			if(advf->has_typecode)
				dbuf_write(outf, advf->typecode, 4);
			else
				dbuf_write_zeroes(outf, 4);
			if(advf->has_creatorcode)
				dbuf_write(outf, advf->creatorcode, 4);
			else
				dbuf_write_zeroes(outf, 4);
			dbuf_writeu16be(outf, advf->has_finderflags?((i64)advf->finderflags):0);
			dbuf_write_zeroes(outf, 6 + 16);
			break;
		}

		// In case something went wrong, try to make sure we're at the expected
		// file position.
		// Note: This might not compensate for all failures, as dbuf_truncate
		// might not be fully implemented for this output type.
		dbuf_truncate(outf, entry_info[k].offset + entry_info[k].len);
	}

done:
	dbuf_close(outf);
	de_free(c, afp_main);
	de_free(c, afp_rsrc);
	ucstring_destroy(fname);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x218, %rsp            # imm = 0x218
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %r15
callq 0xeac74
movq %rax, %rbx
movq 0x68(%r14), %rsi
movq %rax, %rdi
callq 0xead71
cmpq $0x0, 0x10(%rbx)
jg 0xf0ed4
leaq 0x30833(%rip), %rsi     # 0x1216fc
pushq $0x5
popq %rdx
movq %rbx, %rdi
callq 0xeae42
testl %ebp, %ebp
leaq 0x4caa4(%rip), %rax     # 0x13d981
leaq 0x4caa2(%rip), %rsi     # 0x13d986
cmovneq %rax, %rsi
pushq $0x5
popq %rdx
movq %rbx, %rdi
callq 0xeae42
movq 0x20(%r14), %rsi
movl 0x70(%r14), %ecx
movq %r15, %rdi
movq %rbx, 0x30(%rsp)
movq %rbx, %rdx
callq 0xdfd55
movb 0x79(%r14), %al
movq 0x20(%r14), %rdx
movb %al, 0x8(%rdx)
movl 0x74(%r14), %ecx
movq %r15, %rdi
xorl %esi, %esi
callq 0xe4e62
movq %rax, %r12
movq %r14, (%rsp)
cmpb $0x0, 0x78(%r14)
je 0xf0f3a
movq %r12, %rdi
callq 0xe589c
testl %ebp, %ebp
movl $0x51607, %eax          # imm = 0x51607
movl $0x51600, %esi          # imm = 0x51600
cmovneq %rax, %rsi
leaq 0x18a4e(%rip), %rax     # 0x10999f
leaq 0x18a7f(%rip), %r13     # 0x1099d7
cmovneq %rax, %r13
movq %r12, %rdi
callq 0xe5f65
movl $0x20000, %esi          # imm = 0x20000
movq %r12, %rdi
callq 0xe5f65
pushq $0x10
popq %rsi
movq %r12, %rdi
callq 0xe5d20
leaq 0x4ca07(%rip), %rdx     # 0x13d98a
xorl %r14d, %r14d
leaq 0x1c0(%rsp), %rbx
pushq $0x50
popq %rsi
movq %rbx, %rdi
movq %r13, %rcx
xorl %eax, %eax
callq 0xde40c
movq %rbx, %rdi
callq 0x180e0
movq %rax, 0x18(%rsp)
movq (%rsp), %rdx
cmpq $0x0, 0x88(%rdx)
je 0xf0fd6
leaq 0x58(%rsp), %rax
movl $0x3, -0x18(%rax)
movq 0x80(%rdx), %rcx
movq %rcx, -0x8(%rax)
pushq $0x1
popq %r14
jmp 0xf0fdb
leaq 0x40(%rsp), %rax
movl $0x4, (%rax)
movq 0x18(%rsp), %rcx
movq %rcx, 0x10(%rax)
leaq 0x1(%r14), %r13
movq 0x20(%rdx), %rax
cmpb $0x0, 0x28(%rax)
jne 0xf100a
cmpb $0x0, 0x18(%rax)
jne 0xf100a
cmpb $0x0, 0x58(%rax)
jne 0xf100a
cmpb $0x0, 0x38(%rax)
je 0xf1026
imulq $0x18, %r13, %rcx
movl $0x8, 0x40(%rsp,%rcx)
movq $0x10, 0x50(%rsp,%rcx)
orq $0x2, %r14
movq %r14, %r13
cmpb $0x0, 0x7b(%rdx)
jne 0xf1038
cmpb $0x0, 0x7c(%rdx)
jne 0xf1038
cmpb $0x0, 0x7d(%rdx)
je 0xf1056
cmpb $0x0, 0x9(%rax)
jne 0xf1056
imulq $0x18, %r13, %rax
movl $0x9, 0x40(%rsp,%rax)
movq $0x20, 0x50(%rsp,%rax)
incq %r13
cmpb $0x0, 0x38(%rdx)
je 0xf1074
imulq $0x18, %r13, %rax
movl $0x2, 0x40(%rsp,%rax)
movq 0x40(%rdx), %rcx
movq %rcx, 0x50(%rsp,%rax)
incq %r13
testl %ebp, %ebp
jne 0xf1096
cmpb $0x0, 0x10(%rdx)
je 0xf1096
imulq $0x18, %r13, %rax
movl $0x1, 0x40(%rsp,%rax)
movq 0x18(%rdx), %rcx
movq %rcx, 0x50(%rsp,%rax)
incq %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0xe5f1e
imulq $0xc, %r13, %rax
addq $0x1a, %rax
imulq $0x18, %r13, %rbx
xorl %ecx, %ecx
cmpq %rcx, %rbx
je 0xf10c4
movq %rax, 0x48(%rsp,%rcx)
addq 0x50(%rsp,%rcx), %rax
addq $0x18, %rcx
jmp 0xf10af
movq %r15, 0x10(%rsp)
xorl %r14d, %r14d
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movabsq $0x100000000, %r15      # imm = 0x100000000
cmpq %r14, %rbx
je 0xf1139
movl 0x40(%rsp,%r14), %esi
movq %r12, %rdi
callq 0xe5f65
movq 0x48(%rsp,%r14), %rsi
cmpq %rbp, %rsi
jg 0xf111a
movq 0x50(%rsp,%r14), %r13
cmpq %r15, %r13
jge 0xf111a
movq %r12, %rdi
callq 0xe5f65
movq %r12, %rdi
movq %r13, %rsi
callq 0xe5f65
addq $0x18, %r14
jmp 0xf10db
leaq 0x4c88e(%rip), %rsi     # 0x13d9af
xorl %ebx, %ebx
movq 0x10(%rsp), %r15
movq %r15, %rdi
xorl %eax, %eax
callq 0xdf2a5
xorl %ebp, %ebp
jmp 0xf139a
movq (%rsp), %rax
leaq 0x90(%rax), %rcx
movq %rcx, 0x28(%rsp)
addq $0x94, %rax
movq %rax, 0x20(%rsp)
xorl %r14d, %r14d
leaq 0x4c7f2(%rip), %r13     # 0x13d950
movq $0x0, 0x8(%rsp)
xorl %ebp, %ebp
movq 0x10(%rsp), %r15
cmpq %r14, %rbx
je 0xf1395
movl 0x40(%rsp,%r14), %eax
decl %eax
cmpl $0x8, %eax
ja 0xf137a
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movq %rbp, 0x38(%rsp)
movq %r15, %rdi
pushq $0x10
popq %rsi
callq 0xdecaf
movq %r15, %rbp
movq %rax, %r15
movl $0x1, (%rax)
movq (%rsp), %r13
movq 0x28(%r13), %rdx
movq 0x30(%r13), %rsi
movq %r12, %rdi
callq 0xe629a
movq %r15, 0x8(%rsp)
movq %r12, 0x8(%r15)
movq %rbp, %r15
movq 0x60(%r13), %rax
testq %rax, %rax
je 0xf11ea
cmpq $0x0, 0x18(%r13)
jle 0xf11ea
movq %r15, %rdi
movq %r13, %rsi
movq 0x8(%rsp), %rdx
callq *%rax
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xe629a
movq 0x38(%rsp), %rbp
jmp 0xf1290
movq (%rsp), %rax
movq 0x80(%rax), %rdx
movq 0x88(%rax), %rsi
movq %r12, %rdi
jmp 0xf12ac
movq (%rsp), %rax
cmpb $0x0, 0x7b(%rax)
je 0xf1323
movq %r12, %rdi
movq 0x28(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0xe46ba
jmp 0xf132e
movq %r15, %rdi
pushq $0x10
popq %rsi
callq 0xdecaf
movq %rax, %rbp
movl $0x2, (%rax)
movq (%rsp), %r13
movq 0x50(%r13), %rdx
movq 0x58(%r13), %rsi
movq %r12, %rdi
callq 0xe629a
movq %r12, 0x8(%rbp)
movq 0x60(%r13), %rax
testq %rax, %rax
je 0xf1284
cmpq $0x0, 0x40(%r13)
jle 0xf1284
movq %r15, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq *%rax
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xe629a
leaq 0x4c6b9(%rip), %r13     # 0x13d950
jmp 0xf137a
movq %r12, %rdi
leaq 0x1c0(%rsp), %rsi
movq 0x18(%rsp), %rdx
callq 0xe46ba
jmp 0xf137a
movq (%rsp), %r13
movq 0x20(%r13), %rdi
addq $0x28, %rdi
callq 0xf15d2
movq %r12, %rdi
movq %rax, %rsi
callq 0xe5fb0
movq 0x20(%r13), %rdi
addq $0x18, %rdi
callq 0xf15d2
movq %r12, %rdi
movq %rax, %rsi
callq 0xe5fb0
movq 0x20(%r13), %rdi
addq $0x58, %rdi
callq 0xf15d2
movq %r12, %rdi
movq %rax, %rsi
callq 0xe5fb0
movq 0x20(%r13), %rdi
leaq 0x4c643(%rip), %r13     # 0x13d950
addq $0x38, %rdi
callq 0xf15d2
movq %r12, %rdi
movq %rax, %rsi
callq 0xe5fb0
jmp 0xf137a
movq %r12, %rdi
pushq $0x4
popq %rsi
callq 0xe5d20
movq (%rsp), %rax
cmpb $0x0, 0x7c(%rax)
je 0xf134a
movq %r12, %rdi
movq 0x20(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0xe46ba
jmp 0xf1355
movq %r12, %rdi
pushq $0x4
popq %rsi
callq 0xe5d20
movq (%rsp), %rax
cmpb $0x0, 0x7d(%rax)
je 0xf1365
movzwl 0x7e(%rax), %esi
jmp 0xf1367
xorl %esi, %esi
movq %r12, %rdi
callq 0xe5f1e
movq %r12, %rdi
pushq $0x16
popq %rsi
callq 0xe5d20
movq 0x50(%rsp,%r14), %rsi
addq 0x48(%rsp,%r14), %rsi
movq %r12, %rdi
callq 0xe5eb2
addq $0x18, %r14
jmp 0xf116e
movq 0x8(%rsp), %rbx
movq %r12, %rdi
callq 0xe5591
movq %r15, %rdi
movq %rbx, %rsi
callq 0xded32
movq %r15, %rdi
movq %rbp, %rsi
callq 0xded32
movq 0x30(%rsp), %rdi
callq 0xeaf3c
addq $0x218, %rsp            # imm = 0x218
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq