// File: joncampbell123[P]floppytools/kryocomm.cpp
// Function: autodetect_flux_bits_mfm(flux_bits&, kryoflux_event&, _IO_FILE*)
bool autodetect_flux_bits_mfm(struct flux_bits &fb,struct kryoflux_event &ev,FILE *fp) {
    fseek(fp,0,SEEK_SET);
    fb.clear();

    unsigned long hist[256];
    for (unsigned long i=0;i < 256;i++) hist[i] = 0;

    while (kryoflux_read(ev,fp)) {
        if (ev.message == MSG_FLUX) {
            unsigned long ofs = ev.flux_interval;
            if (ofs < 256ul) hist[ofs]++;
        }
    }

    fseek(fp,0,SEEK_SET);

    unsigned long min = ~0UL,max = 0;
    for (unsigned int i=0;i < 256;i++) {
        if (hist[i] != 0ul) {
            if (min > hist[i]) min = hist[i];
            if (max < hist[i]) max = hist[i];
        }
    }

    if (min == ~0UL)
        return false;

    if (max < (min * 4ul))
        return false;

    unsigned long cutoff = min + ((max - min) / 100ul);

    /* look for the first peak, which represents 1010101010101010101010 */
    unsigned int scan = 0;

    unsigned long peak_max[3];
    unsigned int peak_idx[3];

//  fprintf(stderr,"autoscan: min=%lu max=%lu cutoff=%lu\n",min,max,cutoff);

    for (unsigned int peak=0;peak < 3;peak++) {
        peak_max[peak] = 0;
        peak_idx[peak] = 0;
        while (scan < 256 && hist[scan] < cutoff) scan++;
        while (scan < 256 && hist[scan] >= cutoff) {
            if (peak_max[peak] < hist[scan]) {
                peak_max[peak] = hist[scan];
                peak_idx[peak] = scan;
            }
            scan++;
        }
    }

//    printf("autoscan: peaks at %u, %u, %u [%lu, %lu, %lu]\n",
//        peak_idx[0],peak_idx[1],peak_idx[2],
//        peak_max[0],peak_max[1],peak_max[2]);

    /* we require two peaks at least */
    if (peak_idx[0] == 0 || peak_idx[1] == 0)
        return false;

    fb.dist = peak_idx[1] - peak_idx[0];
    if (fb.dist < 8)
        return false;

    if (peak_idx[2] != 0) {
        unsigned long dist2 = peak_idx[2] - peak_idx[1];

//        printf("autoscan: dist=%lu dist2=%lu\n",fb.dist,dist2);
        if (labs((signed long)dist2 - (signed long)fb.dist) < (fb.dist / 4ul)) {
//            printf("autoscan: using peaks 1-2 to average dist (diff=%ld)\n",(signed long)dist2 - (signed long)fb.dist);
            fb.dist = (fb.dist + dist2) / 2ul;
        }
    }

    fb.shortest = peak_idx[0];
    if (fb.shortest <= fb.dist)
        return false;

    /* peak[0] represents 101010101010101010 so to get the shortest (1111111)
     * subtract dist from it */
    fb.shortest -= fb.dist;

//    printf("autoscan: final params shortest=%lu dist=%lu\n",fb.shortest,fb.dist);
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x8a0, %rsp            # imm = 0x8A0
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x20(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x21a0
movq -0x10(%rbp), %rdi
callq 0x71f0
movq $0x0, -0x828(%rbp)
cmpq $0x100, -0x828(%rbp) # imm = 0x100
jae 0x735e
movq -0x828(%rbp), %rax
movq $0x0, -0x820(%rbp,%rax,8)
movq -0x828(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x828(%rbp)
jmp 0x732a
jmp 0x7360
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x6d90
testb $0x1, %al
jne 0x7373
jmp 0x73b9
movq -0x18(%rbp), %rax
movzbl 0x4(%rax), %eax
cmpl $0x1, %eax
jne 0x73b7
movq -0x18(%rbp), %rax
movl (%rax), %eax
movq %rax, -0x830(%rbp)
cmpq $0x100, -0x830(%rbp) # imm = 0x100
jae 0x73b5
movq -0x830(%rbp), %rax
movq -0x820(%rbp,%rax,8), %rcx
addq $0x1, %rcx
movq %rcx, -0x820(%rbp,%rax,8)
jmp 0x73b7
jmp 0x7360
movq -0x20(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x21a0
movq $-0x1, -0x838(%rbp)
movq $0x0, -0x840(%rbp)
movl $0x0, -0x844(%rbp)
cmpl $0x100, -0x844(%rbp)    # imm = 0x100
jae 0x7479
movl -0x844(%rbp), %eax
cmpq $0x0, -0x820(%rbp,%rax,8)
je 0x7463
movq -0x838(%rbp), %rax
movl -0x844(%rbp), %ecx
cmpq -0x820(%rbp,%rcx,8), %rax
jbe 0x7435
movl -0x844(%rbp), %eax
movq -0x820(%rbp,%rax,8), %rax
movq %rax, -0x838(%rbp)
movq -0x840(%rbp), %rax
movl -0x844(%rbp), %ecx
cmpq -0x820(%rbp,%rcx,8), %rax
jae 0x7461
movl -0x844(%rbp), %eax
movq -0x820(%rbp,%rax,8), %rax
movq %rax, -0x840(%rbp)
jmp 0x7463
jmp 0x7465
movl -0x844(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x844(%rbp)
jmp 0x73e8
cmpq $-0x1, -0x838(%rbp)
jne 0x748c
movb $0x0, -0x1(%rbp)
jmp 0x7710
movq -0x840(%rbp), %rax
movq -0x838(%rbp), %rcx
shlq $0x2, %rcx
cmpq %rcx, %rax
jae 0x74ac
movb $0x0, -0x1(%rbp)
jmp 0x7710
movq -0x838(%rbp), %rax
movq %rax, -0x890(%rbp)
movq -0x840(%rbp), %rax
subq -0x838(%rbp), %rax
movl $0x64, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, %rcx
movq -0x890(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x850(%rbp)
movl $0x0, -0x854(%rbp)
movl $0x0, -0x880(%rbp)
cmpl $0x3, -0x880(%rbp)
jae 0x7630
movl -0x880(%rbp), %eax
movq $0x0, -0x870(%rbp,%rax,8)
movl -0x880(%rbp), %eax
movl $0x0, -0x87c(%rbp,%rax,4)
xorl %eax, %eax
cmpl $0x100, -0x854(%rbp)    # imm = 0x100
movb %al, -0x891(%rbp)
jae 0x755c
movl -0x854(%rbp), %eax
movq -0x820(%rbp,%rax,8), %rax
cmpq -0x850(%rbp), %rax
setb %al
movb %al, -0x891(%rbp)
movb -0x891(%rbp), %al
testb $0x1, %al
jne 0x7568
jmp 0x7579
movl -0x854(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x854(%rbp)
jmp 0x752a
jmp 0x757b
xorl %eax, %eax
cmpl $0x100, -0x854(%rbp)    # imm = 0x100
movb %al, -0x892(%rbp)
jae 0x75ad
movl -0x854(%rbp), %eax
movq -0x820(%rbp,%rax,8), %rax
cmpq -0x850(%rbp), %rax
setae %al
movb %al, -0x892(%rbp)
movb -0x892(%rbp), %al
testb $0x1, %al
jne 0x75b9
jmp 0x761a
movl -0x880(%rbp), %eax
movq -0x870(%rbp,%rax,8), %rax
movl -0x854(%rbp), %ecx
cmpq -0x820(%rbp,%rcx,8), %rax
jae 0x7606
movl -0x854(%rbp), %eax
movq -0x820(%rbp,%rax,8), %rcx
movl -0x880(%rbp), %eax
movq %rcx, -0x870(%rbp,%rax,8)
movl -0x854(%rbp), %ecx
movl -0x880(%rbp), %eax
movl %ecx, -0x87c(%rbp,%rax,4)
movl -0x854(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x854(%rbp)
jmp 0x757b
jmp 0x761c
movl -0x880(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x880(%rbp)
jmp 0x74fa
cmpl $0x0, -0x87c(%rbp)
je 0x7642
cmpl $0x0, -0x878(%rbp)
jne 0x764b
movb $0x0, -0x1(%rbp)
jmp 0x7710
movl -0x878(%rbp), %ecx
subl -0x87c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x10(%rbp), %rax
cmpl $0x8, 0xc(%rax)
jae 0x7671
movb $0x0, -0x1(%rbp)
jmp 0x7710
cmpl $0x0, -0x874(%rbp)
je 0x76d6
movl -0x874(%rbp), %eax
subl -0x878(%rbp), %eax
movl %eax, %eax
movq %rax, -0x888(%rbp)
movq -0x888(%rbp), %rax
movq -0x10(%rbp), %rcx
movl 0xc(%rcx), %ecx
subq %rcx, %rax
movq %rax, %rcx
negq %rcx
cmovnsq %rcx, %rax
movq -0x10(%rbp), %rcx
movl 0xc(%rcx), %ecx
shrq $0x2, %rcx
cmpq %rcx, %rax
jae 0x76d4
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
addq -0x888(%rbp), %rax
shrq %rax
movl %eax, %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0xc(%rax)
jmp 0x76d6
movl -0x87c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0xc(%rcx), %eax
ja 0x76f9
movb $0x0, -0x1(%rbp)
jmp 0x7710
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edx
movq -0x10(%rbp), %rax
movl 0x8(%rax), %ecx
subl %edx, %ecx
movl %ecx, 0x8(%rax)
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x8a0, %rsp            # imm = 0x8A0
popq %rbp
retq
nop