// File: /workspace/github_c_makefile_star2_O0/salextpuru[P]speccy-toochain/src/mhmt/mhmt-pack.c
// Function: pack
ULONG pack(void)
{
    ULONG (*get_lz_price)(ULONG position, struct lzcode * lzcode) = NULL; // generates correct bitlen (price) of code
    ULONG (*emit)(struct optchain * optch, ULONG actual_len) = NULL; // emits lzcode to the output bit/byte stream
    ULONG success=1;
    ULONG actual_len; // actual length of packing (to account for ZX headers containing last unpacked bytes)
    UBYTE * hash;
    struct optchain * optch=NULL;
    static struct lzcode codes[MAX_CODES_SIZE]; // generate codes here; static to ensure it's not on the stack
    UBYTE curr_byte, last_byte;
    UWORD index;
    ULONG position;

    // some preparations
    //
    if( wrk.packtype==PK_MLZ ) {
        get_lz_price  = &get_lz_price_megalz;
        emit          = &emit_megalz;

    } else if( wrk.packtype==PK_HRM ) {
        get_lz_price  = &get_lz_price_hrum;
        emit          = &emit_hrum;

    } else if( wrk.packtype==PK_HST ) {
        get_lz_price  = &get_lz_price_hrust;
        emit          = &emit_hrust;

    } else {
        printf("mhmt-pack.c:pack() - format unsupported!\n");
        return 0;
    }

    actual_len = wrk.inlen;

    if( wrk.zxheader ) {
        if( wrk.packtype==PK_HRM ) {
            actual_len -= 5;

        } else if( wrk.packtype==PK_HST ) {
            actual_len -= 6;

        } else {
            printf("mhmt-pack.c:pack() - there must be no zxheader for anything except hrust or hrum!\n");
            return 0;
        }
    }

    // initializations and preparations
    init_tb();
    hash = build_hash(wrk.indata, actual_len);

    if( !hash ) {
        printf("mhmt-pack.c:pack() - build_hash() failed!\n");
        success = 0;
    }

    if( success ) {
        optch = make_optch(actual_len);

        if( !optch ) {
            printf("mhmt-pack.c:pack() - can't make optchain array!\n");
            success = 0;
        }
    }

    // go packing!
    if( success ) {
        if( !wrk.greedy ) { // default optimal coding
            // go generating lzcodes byte-by-byte
            //
            curr_byte = wrk.indata[0];

            //
            for(position=1; position<actual_len; position++) {
                last_byte = curr_byte;
                curr_byte = wrk.indata[position];
                // add current two-byter to the chains
                index = (last_byte<<8) + curr_byte;

                if( !add_tb(index,position) ) {
                    printf("mhmt-pack.c:pack() - add_tb() failed!\n");
                    success = 0;
                    goto ERROR;
                }

                // search lzcodes for given position
                make_lz_codes(position, actual_len, hash, codes);
                // update optimal chain with lzcodes
                update_optch(position, codes, get_lz_price, optch);
            }

            // all input bytes scanned, chain built, so now reverse it (prepare for scanning in output generation part)
            reverse_optch(optch, actual_len);

        } else { // greedy coding
            printf("mhmt-pack.c:pack() - greedy coding not supported!\n");
            success = 0;
        }

        // data built, now emit packed file
        success = success && (*emit)(optch, actual_len);
    }

ERROR:
    free_optch(optch);
    destroy_hash(hash);
    return success;
}

// Assembly:
subq $0x48, %rsp
movq $0x0, 0x38(%rsp)
movq $0x0, 0x30(%rsp)
movl $0x1, 0x2c(%rsp)
movq $0x0, 0x18(%rsp)
leaq 0x8fa2(%rip), %rax      # 0xe3a0
cmpl $0x1, (%rax)
jne 0x541d
leaq -0x11fa(%rip), %rax     # 0x4210
movq %rax, 0x38(%rsp)
leaq -0x41f6(%rip), %rax     # 0x1220
movq %rax, 0x30(%rsp)
jmp 0x5488
leaq 0x8f7c(%rip), %rax      # 0xe3a0
cmpl $0x2, (%rax)
jne 0x5443
leaq -0x1070(%rip), %rax     # 0x43c0
movq %rax, 0x38(%rsp)
leaq -0x34cc(%rip), %rax     # 0x1f70
movq %rax, 0x30(%rsp)
jmp 0x5486
leaq 0x8f56(%rip), %rax      # 0xe3a0
cmpl $0x3, (%rax)
jne 0x5469
leaq -0xef6(%rip), %rax      # 0x4560
movq %rax, 0x38(%rsp)
leaq -0x2c92(%rip), %rax     # 0x27d0
movq %rax, 0x30(%rsp)
jmp 0x5484
leaq 0x4973(%rip), %rdi      # 0x9de3
movb $0x0, %al
callq 0x1040
movl $0x0, 0x44(%rsp)
jmp 0x56c6
jmp 0x5486
jmp 0x5488
leaq 0x8f11(%rip), %rax      # 0xe3a0
movl 0x48(%rax), %eax
movl %eax, 0x28(%rsp)
leaq 0x8f03(%rip), %rax      # 0xe3a0
cmpl $0x0, 0xc(%rax)
je 0x54f4
leaq 0x8ef6(%rip), %rax      # 0xe3a0
cmpl $0x2, (%rax)
jne 0x54bc
movl 0x28(%rsp), %eax
subl $0x5, %eax
movl %eax, 0x28(%rsp)
jmp 0x54f2
leaq 0x8edd(%rip), %rax      # 0xe3a0
cmpl $0x3, (%rax)
jne 0x54d5
movl 0x28(%rsp), %eax
subl $0x6, %eax
movl %eax, 0x28(%rsp)
jmp 0x54f0
leaq 0x4931(%rip), %rdi      # 0x9e0d
movb $0x0, %al
callq 0x1040
movl $0x0, 0x44(%rsp)
jmp 0x56c6
jmp 0x54f2
jmp 0x54f4
callq 0x61b0
leaq 0x8ea0(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rdi
movl 0x28(%rsp), %esi
callq 0x3a70
movq %rax, 0x20(%rsp)
cmpq $0x0, 0x20(%rsp)
jne 0x5530
leaq 0x493f(%rip), %rdi      # 0x9e60
movb $0x0, %al
callq 0x1040
movl $0x0, 0x2c(%rsp)
cmpl $0x0, 0x2c(%rsp)
je 0x5565
movl 0x28(%rsp), %edi
callq 0x5140
movq %rax, 0x18(%rsp)
cmpq $0x0, 0x18(%rsp)
jne 0x5563
leaq 0x4937(%rip), %rdi      # 0x9e8b
movb $0x0, %al
callq 0x1040
movl $0x0, 0x2c(%rsp)
jmp 0x5565
cmpl $0x0, 0x2c(%rsp)
je 0x56a8
leaq 0x8e29(%rip), %rax      # 0xe3a0
cmpl $0x0, 0x4(%rax)
jne 0x565e
leaq 0x8e18(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movb (%rax), %al
movb %al, 0x17(%rsp)
movl $0x1, 0x10(%rsp)
movl 0x10(%rsp), %eax
cmpl 0x28(%rsp), %eax
jae 0x564e
movb 0x17(%rsp), %al
movb %al, 0x16(%rsp)
leaq 0x8de9(%rip), %rax      # 0xe3a0
movq 0x40(%rax), %rax
movl 0x10(%rsp), %ecx
movb (%rax,%rcx), %al
movb %al, 0x17(%rsp)
movzbl 0x16(%rsp), %eax
shll $0x8, %eax
movzbl 0x17(%rsp), %ecx
addl %ecx, %eax
movw %ax, 0x14(%rsp)
movw 0x14(%rsp), %ax
movl 0x10(%rsp), %esi
movzwl %ax, %edi
callq 0x6240
cmpl $0x0, %eax
jne 0x560b
leaq 0x48c5(%rip), %rdi      # 0x9ebc
movb $0x0, %al
callq 0x1040
movl $0x0, 0x2c(%rsp)
jmp 0x56aa
movl 0x10(%rsp), %edi
movl 0x28(%rsp), %esi
movq 0x20(%rsp), %rdx
leaq 0x8dd1(%rip), %rcx      # 0xe3f0
callq 0x3b90
movl 0x10(%rsp), %edi
movq 0x38(%rsp), %rdx
movq 0x18(%rsp), %rcx
leaq 0x8db7(%rip), %rsi      # 0xe3f0
callq 0x5200
movl 0x10(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10(%rsp)
jmp 0x559a
movq 0x18(%rsp), %rdi
movl 0x28(%rsp), %esi
callq 0x5330
jmp 0x5674
leaq 0x487e(%rip), %rdi      # 0x9ee3
movb $0x0, %al
callq 0x1040
movl $0x0, 0x2c(%rsp)
xorl %eax, %eax
cmpl $0x0, 0x2c(%rsp)
movb %al, 0xf(%rsp)
je 0x569b
movq 0x30(%rsp), %rax
movq 0x18(%rsp), %rdi
movl 0x28(%rsp), %esi
callq *%rax
cmpl $0x0, %eax
setne %al
movb %al, 0xf(%rsp)
movb 0xf(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x2c(%rsp)
jmp 0x56aa
movq 0x18(%rsp), %rdi
callq 0x51e0
movq 0x20(%rsp), %rdi
callq 0x3b70
movl 0x2c(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x44(%rsp), %eax
addq $0x48, %rsp
retq
nop