// File: /workspace/github_c_makefile_star2_O0/jsummers[P]deark/modules/dms.c
// Function: decompress_dms_heavy
static void decompress_dms_heavy(struct lzh_ctx *cctx, struct dmslzh_params *lzhp,
	struct dmsheavy_cmpr_state *hvst)
{
	deark *c = cctx->c;
	UI rb_size;
	int ret;
	int saved_indent_level;
	char pos_descr[32];

	de_dbg_indent_save(c, &saved_indent_level);

	if(lzhp->cmpr_type != hvst->cmpr_type) {
		de_dfilter_set_errorf(c, cctx->dres, cctx->modname,
			"Mixing Heavy compression types is not supported");
		goto done;
	}

	if(lzhp->cmpr_type==DMSCMPR_HEAVY1) {
		rb_size = 4096;
		cctx->heavy_np = 14; // for heavy1
	}
	else {
		rb_size = 8192;
		cctx->heavy_np = 15; // for heavy2
	}

	if(!hvst->ringbuf) {
		hvst->ringbuf = de_lz77buffer_create(cctx->c, rb_size);
	}

	hvst->ringbuf->userdata = (void*)cctx;
	hvst->ringbuf->writebyte_cb = lha5like_lz77buf_writebytecb;

	if(!cctx->dcmpro->len_known) {
		// I think we (may) have to know the output length, because zero-length Huffman
		// codes are(?) possible, and unlike lh5 we aren't told how many codes there are.
		de_dfilter_set_errorf(cctx->c, cctx->dres, cctx->modname, "Internal error");
		goto done;
	}

	if(lzhp->dms_track_flags & 0x02) {
		dmsheavy_discard_tree(c, &hvst->literals_tree);
		dmsheavy_discard_tree(c, &hvst->offsets_tree);
		hvst->trees_exist = 0;
	}

	if(!hvst->trees_exist) {
		hvst->trees_exist = 1;
		de_dbg2(c, "c tree");
		de_dbg_indent(c, 1);
		ret = dmsheavy_read_tree(cctx, &hvst->literals_tree, 9, 5);
		de_dbg_indent(c, -1);
		if(!ret) goto done;

		de_dbg2(c, "p tree");
		de_dbg_indent(c, 1);
		ret = dmsheavy_read_tree(cctx, &hvst->offsets_tree, 5, 4);
		de_dbg_indent(c, -1);
		if(!ret) goto done;
	}

	de_bitreader_describe_curpos(&cctx->bitrd, pos_descr, sizeof(pos_descr));
	de_dbg2(c, "cmpr data codes at %s", pos_descr);
	de_dbg_indent(c, 1);
	while(1) {
		UI code;

		if(cctx->bitrd.eof_flag) goto done;
		if(lzh_have_enough_output(cctx)) goto done;

		code = read_next_code_using_tree(cctx, &hvst->literals_tree);
		if(cctx->bitrd.eof_flag) goto done;
		if(c->debug_level>=3) {
			de_dbg3(c, "code: %u (opos=%"I64_FMT")", code, cctx->nbytes_written);
		}

		if(code < 256) { // literal
			de_lz77buffer_add_literal_byte(hvst->ringbuf, (u8)code);
		}
		else { // repeat previous bytes
			UI offset;
			UI length;
			UI ocode1;

			length = code-253;
			ocode1 = read_next_code_using_tree(cctx, &hvst->offsets_tree);
			if(cctx->bitrd.eof_flag) goto done;

			if(ocode1 == cctx->heavy_np-1) {
				offset = hvst->heavy_prev_offset;
			}
			else {
				if(ocode1 < 1) {
					offset = ocode1;
				}
				else {
					UI ocode2;

					ocode2 = (UI)de_bitreader_getbits(&cctx->bitrd, ocode1-1);
					if(cctx->bitrd.eof_flag) goto done;
					offset = ocode2 | (1U<<(ocode1-1));
				}
				hvst->heavy_prev_offset = offset;
			}

			de_lz77buffer_copy_from_hist(hvst->ringbuf,
				(UI)(hvst->ringbuf->curpos-offset-1), length);
		}
	}

done:
	de_dbg_indent_restore(c, saved_indent_level);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rdi
leaq -0x2c(%rbp), %rsi
callq 0x15b580
movq -0x10(%rbp), %rax
movl (%rax), %eax
movq -0x18(%rbp), %rcx
cmpl (%rcx), %eax
je 0x673f1
movq -0x20(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdx
leaq 0x14296a(%rip), %rcx    # 0x1a9d4f
movb $0x0, %al
callq 0x177450
jmp 0x67727
movq -0x10(%rbp), %rax
cmpl $0x5, (%rax)
jne 0x6740e
movl $0x1000, -0x24(%rbp)    # imm = 0x1000
movq -0x8(%rbp), %rax
movl $0xe, 0x68(%rax)
jmp 0x67420
movl $0x2000, -0x24(%rbp)    # imm = 0x2000
movq -0x8(%rbp), %rax
movl $0xf, 0x68(%rax)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x8(%rax)
jne 0x67445
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movl -0x24(%rbp), %esi
callq 0x1785d0
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x8(%rbp), %rcx
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
leaq 0x2dd(%rip), %rcx       # 0x67740
movq %rcx, 0x8(%rax)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rax
cmpb $0x0, 0x8(%rax)
jne 0x6749f
movq -0x8(%rbp), %rax
movq (%rax), %rdi
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdx
leaq 0x1428ec(%rip), %rcx    # 0x1a9d7f
movb $0x0, %al
callq 0x177450
jmp 0x67727
movq -0x10(%rbp), %rax
movzbl 0x4(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x674d9
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x18, %rsi
callq 0x677a0
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
callq 0x677a0
movq -0x18(%rbp), %rax
movb $0x0, 0x10(%rax)
movq -0x18(%rbp), %rax
cmpb $0x0, 0x10(%rax)
jne 0x6759f
movq -0x18(%rbp), %rax
movb $0x1, 0x10(%rax)
movq -0x20(%rbp), %rdi
leaq 0x142894(%rip), %rsi    # 0x1a9d8e
movb $0x0, %al
callq 0x15b350
movq -0x20(%rbp), %rdi
movl $0x1, %esi
callq 0x15b560
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x18, %rsi
movl $0x9, %edx
movl $0x5, %ecx
callq 0x677e0
movl %eax, -0x28(%rbp)
movq -0x20(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x15b560
cmpl $0x0, -0x28(%rbp)
jne 0x67546
jmp 0x67727
movq -0x20(%rbp), %rdi
leaq 0x142844(%rip), %rsi    # 0x1a9d95
movb $0x0, %al
callq 0x15b350
movq -0x20(%rbp), %rdi
movl $0x1, %esi
callq 0x15b560
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
movl $0x5, %edx
movl $0x4, %ecx
callq 0x677e0
movl %eax, -0x28(%rbp)
movq -0x20(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x15b560
cmpl $0x0, -0x28(%rbp)
jne 0x6759d
jmp 0x67727
jmp 0x6759f
movq -0x8(%rbp), %rdi
addq $0x38, %rdi
leaq -0x50(%rbp), %rsi
movl $0x20, %edx
callq 0x16a540
movq -0x20(%rbp), %rdi
leaq -0x50(%rbp), %rdx
leaq 0x1427d8(%rip), %rsi    # 0x1a9d9c
movb $0x0, %al
callq 0x15b350
movq -0x20(%rbp), %rdi
movl $0x1, %esi
callq 0x15b560
movq -0x8(%rbp), %rax
cmpb $0x0, 0x50(%rax)
je 0x675e8
jmp 0x67727
movq -0x8(%rbp), %rdi
callq 0x67970
cmpl $0x0, %eax
je 0x675fb
jmp 0x67727
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x18, %rsi
callq 0x679c0
movl %eax, -0x54(%rbp)
movq -0x8(%rbp), %rax
cmpb $0x0, 0x50(%rax)
je 0x6761e
jmp 0x67727
movq -0x20(%rbp), %rax
cmpl $0x3, (%rax)
jl 0x67644
movq -0x20(%rbp), %rdi
movl -0x54(%rbp), %edx
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rcx
leaq 0x142775(%rip), %rsi    # 0x1a9db2
movb $0x0, %al
callq 0x15b400
cmpl $0x100, -0x54(%rbp)     # imm = 0x100
jae 0x67665
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0x54(%rbp), %eax
movzbl %al, %esi
callq 0x178880
jmp 0x67722
movl -0x54(%rbp), %eax
subl $0xfd, %eax
movl %eax, -0x5c(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
callq 0x679c0
movl %eax, -0x60(%rbp)
movq -0x8(%rbp), %rax
cmpb $0x0, 0x50(%rax)
je 0x67693
jmp 0x67727
movl -0x60(%rbp), %eax
movq -0x8(%rbp), %rcx
movl 0x68(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x676b0
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x58(%rbp)
jmp 0x67701
cmpl $0x1, -0x60(%rbp)
jae 0x676be
movl -0x60(%rbp), %eax
movl %eax, -0x58(%rbp)
jmp 0x676f7
movq -0x8(%rbp), %rdi
addq $0x38, %rdi
movl -0x60(%rbp), %esi
subl $0x1, %esi
callq 0x16a390
movl %eax, -0x64(%rbp)
movq -0x8(%rbp), %rax
cmpb $0x0, 0x50(%rax)
je 0x676e0
jmp 0x67727
movl -0x64(%rbp), %eax
movl -0x60(%rbp), %ecx
subl $0x1, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
orl %ecx, %eax
movl %eax, -0x58(%rbp)
movl -0x58(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movl 0x10(%rax), %esi
subl -0x58(%rbp), %esi
subl $0x1, %esi
movl -0x5c(%rbp), %edx
callq 0x1788e0
jmp 0x675d9
movq -0x20(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x15b5a0
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)