// File: /workspace/github_c_makefile_star2_O3/excess-c64[P]lib1541img/src/lib/1541img/cbmdosvfsreader.c
// Function: probeCbmdosFsOptions
SOEXPORT int probeCbmdosFsOptions(CbmdosFsOptions *options, const D64 *d64)
{
    CbmdosFsOptions probeopts = CFO_DEFAULT;
    if (options->flags & CFF_RECOVER)
    {
	probeopts.flags |= CFF_RECOVER;
    }

    uint8_t bamprobedolphin[5][21] = {{ 0 }};
    uint8_t bamprobespeed[5][21] = {{ 0 }};

    const uint8_t *bam = Sector_rcontent(D64_rsector(d64, 18, 0));
    if (D64_tracks(d64) > 35)
    {
	if (bam[2] == 0x50)
	{
	    probeopts.flags |= CFF_PROLOGICDOSBAM;
	    for (uint8_t trackno = 36; trackno < 41; ++trackno)
	    {
		uint8_t sectors = Track_sectors(D64_rtrack(d64, trackno));
		parseTrackBam(bamprobespeed[trackno-36],
			sectors, bam + 4*trackno);
	    }
	}
	else
	{
	    int dolphinok = 1;
	    int speedok = 1;
	    for (uint8_t trackno = 36; trackno < 41; ++trackno)
	    {
		uint8_t sectors = Track_sectors(D64_rtrack(d64, trackno));
		if (parseTrackBam(bamprobedolphin[trackno-36],
			    sectors, bam + 0x1c + 4*trackno) < 0)
		{
		    dolphinok = 0;
		}
		if (parseTrackBam(bamprobespeed[trackno-36],
			    sectors, bam + 0x30 + 4*trackno) < 0)
		{
		    speedok = 0;
		}
	    }
	    if (dolphinok)
	    {
		probeopts.flags |= CFF_DOLPHINDOSBAM;
	    }
	    if (speedok)
	    {
		probeopts.flags |= CFF_SPEEDDOSBAM;
	    }
	}
    }

    const Sector *dirsect = D64_rsector(d64, 18, 1);

    uint8_t rdmap[42][21] = { { 0 } };
    rdmap[17][0] = 1;
    rdmap[17][1] = 1;

    int firstfile = 1;
    while (dirsect)
    {
        const uint8_t *dirbytes = Sector_rcontent(dirsect);
        for (uint8_t dirpos = 0; dirpos < 8; ++dirpos)
        {
            const uint8_t *direntry = dirbytes + dirpos * 0x20;
            if (direntry[2])
            {
                CbmdosFileType type = direntry[2] & 0xf;
		if (type < CFT_DEL || type > CFT_REL)
		{
		    logmsg(L_ERROR, "probeCbmdosFsOptions: invalid file type "
			    "found.");
		    if (probeopts.flags & CFF_RECOVER) goto nextfile;
		    return -1;
		}
		if (type != CFT_DEL)
		{
		    uint8_t track = direntry[3];
		    uint8_t sector = direntry[4];
                    if (track == 18)
                    {
                        if (sector == 0 || sector == 1)
                        {
                            track = 0;
                        }
                        else if (firstfile)
                        {
                            probeopts.flags |= CFF_TALLOC_PREFDIRTRACK;
                        }
                    }
                    int doingsidesects = 0;
		    while (track)
		    {
			if (track > 40)
			{
			    probeopts.flags &= ~CFF_40TRACK;
			    probeopts.flags |= CFF_42TRACK;
			}
			else if (track > 35 && !(probeopts.flags & CFF_42TRACK))
			{
			    probeopts.flags |= CFF_40TRACK;
			}
			else if (track == 18)
			{
			    probeopts.flags |= CFF_FILESONDIRTRACK;
			}
			const Sector *filesector = D64_rsector(
				d64, track, sector);
			if (!filesector)
			{
			    logfmt(L_ERROR, "probeCbmdosFsOptions: "
				    "non-existent sector %d/%d found.",
				    track, sector);
			    if (probeopts.flags & CFF_RECOVER) goto nextfile;
			    return -1;
			}
                        if (rdmap[track-1][sector])
                        {
			    logmsg(L_ERROR, "probeCbmdosFsOptions: "
				    "corrupt filesystem, sector used twice.");
			    if (probeopts.flags & CFF_RECOVER) goto nextfile;
			    return -1;
                        }
                        rdmap[track-1][sector] = 1;
			const uint8_t *sectorbytes = Sector_rcontent(
				D64_rsector(d64, track, sector));
			track = sectorbytes[0];
			sector = sectorbytes[1];
                        if (!track && !doingsidesects && type == CFT_REL)
                        {
                            doingsidesects = 1;
                            track = direntry[0x15];
                            sector = direntry[0x16];
                        }
		    }
		}
nextfile:
		firstfile = 0;
            }
        }
        if (dirbytes[0])
        {
            dirsect = D64_rsector(d64, dirbytes[0], dirbytes[1]);
            if (!dirsect)
            {
                logfmt(L_ERROR, "probeCbmdosFsOptions: Non-existent sector "
			"%d/%d found.", dirbytes[0], dirbytes[1]);
		if (probeopts.flags & CFF_RECOVER) goto done;
		return -1;
            }
	    if (rdmap[dirbytes[0]-1][dirbytes[1]])
            {
                logmsg(L_ERROR, "probeCbmdosFsOptions: corrupt filesystem, "
			"sector used twice.");
                if (!(probeopts.flags & CFF_RECOVER)) return -1;
            }
	    if (dirbytes[0] > 40)
	    {
		probeopts.flags &= ~CFF_40TRACK;
		probeopts.flags |= CFF_42TRACK;
	    }
	    else if (dirbytes[0] > 35 && !(probeopts.flags & CFF_42TRACK))
	    {
		probeopts.flags |= CFF_40TRACK;
	    }
	    else if (dirbytes[0] != 18)
	    {
		probeopts.flags |= CFF_ALLOWLONGDIR;
	    }
	    rdmap[dirbytes[0]-1][dirbytes[1]] = 1;
        }
        else dirsect = 0;
    }

    if ((probeopts.flags & CFF_DOLPHINDOSBAM)
	    && memcmp(rdmap+35, bamprobedolphin, sizeof bamprobedolphin))
    {
	probeopts.flags &= ~CFF_DOLPHINDOSBAM;
    }
    if ((probeopts.flags & CFF_SPEEDDOSBAM)
	    && memcmp(rdmap+35, bamprobespeed, sizeof bamprobespeed))
    {
	probeopts.flags &= ~CFF_SPEEDDOSBAM;
    }
    if ((probeopts.flags & CFF_PROLOGICDOSBAM)
	    && memcmp(rdmap+35, bamprobespeed, sizeof bamprobespeed))
    {
	probeopts.flags &= ~CFF_PROLOGICDOSBAM;
    }

    int hasfreeblocks = 0;
    for (uint8_t trackno = 1;
	    trackno < (D64_type(d64) == D64_STANDARD ? 36 : 41); ++trackno)
    {
	uint8_t sectors = Track_sectors(D64_rtrack(d64, trackno));
	for (uint8_t sectno = 0; sectno < sectors; ++sectno)
	{
	    if (!rdmap[trackno-1][sectno])
	    {
		hasfreeblocks = 1;
		goto checkzerofree;
	    }
	}
    }

checkzerofree:
    if (hasfreeblocks)
    {
	int zerofree = 1;
	for (uint8_t trackno = 1; trackno < 36; ++trackno)
	{
	    if (bam[4*trackno])
	    {
		zerofree = 0;
		break;
	    }
	}

	if (D64_type(d64) == D64_STANDARD)
	{
	    if (zerofree) probeopts.flags |= CFF_ZEROFREE;
	}
	else if (zerofree)
	{
	    if (probeopts.flags & CFF_PROLOGICDOSBAM)
	    {
		for (uint8_t trackno = 36; trackno < 41; ++trackno)
		{
		    if (bam[4*trackno])
		    {
			zerofree = 0;
			break;
		    }
		}
		if (zerofree) probeopts.flags |= CFF_ZEROFREE;
	    }
	    else
	    {
		int havedolphin = 0;
		int havespeed = 0;
		if (!memcmp(rdmap+35, bamprobedolphin,
			sizeof bamprobedolphin))
		{
		    havedolphin = 1;
		    for (uint8_t trackno = 36; trackno < 41; ++trackno)
		    {
			if (bam[4*trackno + 0x1c])
			{
			    zerofree = 0;
			    break;
			}
		    }
		}
		if (!memcmp(rdmap+35, bamprobespeed,
			    sizeof bamprobespeed))
		{
		    havespeed = 1;
		    for (uint8_t trackno = 36; trackno < 41; ++trackno)
		    {
			if (bam[4*trackno + 0x30])
			{
			    zerofree = 0;
			    break;
			}
		    }
		}
		if (zerofree)
		{
		    probeopts.flags |= CFF_ZEROFREE;
		    if (havedolphin) probeopts.flags |= CFF_DOLPHINDOSBAM;
		    if (havespeed) probeopts.flags |= CFF_SPEEDDOSBAM;
		}
	    }
	}
    }

done:
    memcpy(options, &probeopts, sizeof probeopts);
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x488, %rsp            # imm = 0x488
movq 0xb538(%rip), %rax      # 0x13fe0
movl $0x100, %r14d           # imm = 0x100
movq %rdi, 0x28(%rsp)
andl (%rdi), %r14d
orl (%rax), %r14d
movq %rsi, %rbp
xorps %xmm0, %xmm0
movups %xmm0, 0xf9(%rsp)
movaps %xmm0, 0xf0(%rsp)
movaps %xmm0, 0xe0(%rsp)
movaps %xmm0, 0xd0(%rsp)
movaps %xmm0, 0xc0(%rsp)
movaps %xmm0, 0xb0(%rsp)
movaps %xmm0, 0xa0(%rsp)
movups %xmm0, 0x89(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
movq %rsi, %rdi
movl $0x12, %esi
xorl %edx, %edx
callq 0x50c0
movq %rax, %rdi
callq 0x5670
movq %rax, %r15
movq %rbp, %rdi
callq 0x55f0
cmpb $0x24, %al
movq %r15, 0x18(%rsp)
movq %rbp, 0x10(%rsp)
jb 0x8c6f
movl %r14d, 0x20(%rsp)
cmpb $0x50, 0x2(%r15)
jne 0x8bb6
movq %r15, %rbx
addq $0x90, %rbx
movq $-0x5, %r14
leaq 0x30(%rsp), %r12
leal 0x29(%r14), %eax
movzbl %al, %esi
movq %rbp, %rdi
callq 0x5060
movq %rax, %rdi
callq 0x5740
movzbl %al, %esi
movq %r12, %rdi
movq %rbx, %rdx
callq 0x89c6
addq $0x15, %r12
addq $0x4, %rbx
incq %r14
jne 0x8b76
movl 0x20(%rsp), %r14d
orl $0x40, %r14d
jmp 0x8c6f
movq %r15, %rbx
addq $0xc0, %rbx
movl $0x1, 0x4(%rsp)
movq $-0x5, %r15
leaq 0xa0(%rsp), %r12
leaq 0x30(%rsp), %r13
movl $0x1, %r14d
leal 0x29(%r15), %eax
movzbl %al, %esi
movq %rbp, %rdi
callq 0x5060
movq %rax, %rdi
callq 0x5740
leaq -0x14(%rbx), %rdx
movzbl %al, %ebp
movq %r12, %rdi
movl %ebp, %esi
callq 0x89c6
testl %eax, %eax
movl 0x4(%rsp), %eax
movl $0x0, %ecx
cmovsl %ecx, %eax
movl %eax, 0x4(%rsp)
movq %r13, %rdi
movl %ebp, %esi
movq 0x10(%rsp), %rbp
movq %rbx, %rdx
callq 0x89c6
testl %eax, %eax
movl $0x0, %eax
cmovsl %eax, %r14d
addq $0x15, %r12
addq $0x15, %r13
addq $0x4, %rbx
incq %r15
jne 0x8be2
movl 0x20(%rsp), %ecx
movl %ecx, %eax
orl $0x10, %eax
cmpl $0x0, 0x4(%rsp)
cmovel %ecx, %eax
movl %eax, %ecx
orl $0x20, %ecx
testl %r14d, %r14d
movl %ecx, %r14d
cmovel %eax, %r14d
movq 0x18(%rsp), %r15
movq %rbp, %rdi
movl $0x12, %esi
movl $0x1, %edx
callq 0x50c0
movq %rax, %r13
leaq 0x110(%rsp), %r12
movl $0x372, %edx            # imm = 0x372
movq %r12, %rdi
xorl %esi, %esi
callq 0x5320
movw $0x101, 0x165(%r12) # imm = 0x101
testq %r13, %r13
je 0x8f6a
movl $0x1, %r15d
movq %r13, %rdi
callq 0x5670
xorl %ebp, %ebp
movq %rax, 0x8(%rsp)
movq %rbp, %r12
shlq $0x5, %r12
movb 0x2(%rax,%r12), %bl
testb %bl, %bl
je 0x8e5f
andb $0xf, %bl
cmpb $0x5, %bl
jb 0x8d09
movl $0x1, %edi
leaq 0x60af(%rip), %rsi      # 0xed9b
callq 0x591c
btl $0x8, %r14d
jae 0x8f4e
xorl %r15d, %r15d
movq 0x8(%rsp), %rax
jmp 0x8e5f
testb %bl, %bl
je 0x8e26
addq %rax, %r12
movzbl 0x3(%r12), %ecx
testl %ecx, %ecx
je 0x8e2b
movb 0x4(%r12), %al
cmpl $0x12, %ecx
jne 0x8d42
cmpb $0x2, %al
jb 0x8cfc
movl %r14d, %ecx
orl $0x1000, %ecx           # imm = 0x1000
testl %r15d, %r15d
cmovnel %ecx, %r14d
movb $0x12, %cl
leaq 0x16(%r12), %rdx
movq %rdx, 0x20(%rsp)
movl $0x0, 0x4(%rsp)
movzbl %cl, %r13d
cmpb $0x29, %r13b
jb 0x8d68
andl $-0xd, %r14d
orl $0x8, %r14d
jmp 0x8d89
cmpb $0x24, %cl
jb 0x8d7b
movl %r14d, %ecx
andl $0x8, %ecx
jne 0x8d7b
orl $0x4, %r14d
jmp 0x8d89
movl %r14d, %ecx
orl $0x2, %ecx
cmpl $0x12, %r13d
cmovel %ecx, %r14d
movl %r14d, %r15d
movzbl %al, %r14d
movq 0x10(%rsp), %rdi
movl %r13d, %esi
movl %r14d, %edx
callq 0x50c0
testq %rax, %rax
je 0x8e30
leal -0x1(%r13), %eax
leaq (%rax,%rax,4), %rcx
leaq (%rax,%rcx,4), %rax
addq %rsp, %rax
addq $0x110, %rax            # imm = 0x110
cmpb $0x0, (%r14,%rax)
jne 0x8e6e
addq %r14, %rax
movb $0x1, (%rax)
movq 0x10(%rsp), %rdi
movl %r13d, %esi
movl %r14d, %edx
callq 0x50c0
movq %rax, %rdi
callq 0x5670
leaq 0x1(%rax), %rdx
movb (%rax), %cl
cmpb $0x4, %bl
jne 0x8e14
testb %cl, %cl
jne 0x8e14
cmpl $0x0, 0x4(%rsp)
movl %r15d, %r14d
jne 0x8e17
movb 0x15(%r12), %cl
movl $0x1, 0x4(%rsp)
movq 0x20(%rsp), %rdx
jmp 0x8e17
movl %r15d, %r14d
movb (%rdx), %al
testb %cl, %cl
jne 0x8d54
jmp 0x8cfc
xorl %r15d, %r15d
jmp 0x8e5f
movl %ecx, %r15d
jmp 0x8e5f
movl $0x1, %edi
leaq 0x5f8e(%rip), %rsi      # 0xedca
movl %r13d, %edx
movl %r14d, %ecx
xorl %eax, %eax
callq 0x5949
movl %r15d, %r14d
xorl %r15d, %r15d
btl $0x8, %r14d
movq 0x8(%rsp), %rax
jae 0x8f4e
incq %rbp
cmpq $0x8, %rbp
jne 0x8cc4
jmp 0x8e92
movl $0x1, %edi
leaq 0x5f87(%rip), %rsi      # 0xee01
callq 0x591c
btl $0x8, %r15d
jae 0x8f4e
movl %r15d, %r14d
jmp 0x8cfc
movq %rax, %rbx
movb (%rax), %al
testb %al, %al
je 0x8f58
movzbl 0x1(%rbx), %edx
movzbl %al, %esi
movq 0x10(%rsp), %rdi
callq 0x50c0
movq %rax, %r13
movb (%rbx), %al
movzbl %al, %edx
testq %r13, %r13
je 0x90f6
leaq (%rdx,%rdx,4), %rcx
leaq (%rdx,%rcx,4), %rcx
movzbl 0x1(%rbx), %edx
addq %rsp, %rcx
addq $0x110, %rcx            # imm = 0x110
cmpb $0x0, -0x15(%rdx,%rcx)
je 0x8efd
movl $0x1, %edi
leaq 0x5f17(%rip), %rsi      # 0xee01
callq 0x591c
btl $0x8, %r14d
jae 0x8f4e
movq 0x8(%rsp), %rax
movb (%rax), %al
cmpb $0x29, %al
jb 0x8f0b
andl $-0xd, %r14d
orl $0x8, %r14d
jmp 0x8f27
cmpb $0x24, %al
jb 0x8f1d
movl %r14d, %ecx
andl $0x8, %ecx
jne 0x8f1d
orl $0x4, %r14d
jmp 0x8f27
xorl %ecx, %ecx
cmpb $0x12, %al
setne %cl
orl %ecx, %r14d
movzbl %al, %eax
leaq (%rax,%rax,4), %rcx
leaq (%rax,%rcx,4), %rax
movq 0x8(%rsp), %rcx
movzbl 0x1(%rcx), %ecx
addq %rsp, %rax
addq $0x110, %rax            # imm = 0x110
movb $0x1, -0x15(%rcx,%rax)
jmp 0x8cb5
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x90a5
movq 0x18(%rsp), %r15
movq 0x10(%rsp), %rbp
leaq 0x110(%rsp), %r12
testb $0x10, %r14b
je 0x8f96
leaq 0x3ef(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
movl $0x69, %edx
callq 0x5540
movl %r14d, %ecx
andl $-0x11, %ecx
testl %eax, %eax
cmovnel %ecx, %r14d
testb $0x20, %r14b
je 0x8fbf
leaq 0x3ef(%rsp), %rdi
leaq 0x30(%rsp), %rsi
movl $0x69, %edx
callq 0x5540
movl %r14d, %ecx
andl $-0x21, %ecx
testl %eax, %eax
cmovnel %ecx, %r14d
testb $0x40, %r14b
je 0x8fe8
leaq 0x3ef(%rsp), %rdi
leaq 0x30(%rsp), %rsi
movl $0x69, %edx
callq 0x5540
movl %r14d, %ecx
andl $-0x41, %ecx
testl %eax, %eax
cmovnel %ecx, %r14d
movq %rbp, %rdi
callq 0x5430
movb $0x1, %bl
movzbl %bl, %esi
movq %rbp, %rdi
callq 0x5060
movq %rax, %rdi
callq 0x5740
testb %al, %al
je 0x901d
movzbl %al, %eax
xorl %ecx, %ecx
cmpb $0x0, (%r12,%rcx)
je 0x904d
incq %rcx
cmpq %rcx, %rax
jne 0x900e
incb %bl
movzbl %bl, %ebp
movq 0x10(%rsp), %rdi
callq 0x5430
xorl %ecx, %ecx
testl %eax, %eax
setne %cl
leal (%rcx,%rcx,4), %eax
addl $0x24, %eax
addq $0x15, %r12
cmpl %ebp, %eax
movq 0x10(%rsp), %rbp
movq 0x18(%rsp), %r15
ja 0x8ff2
jmp 0x908e
movb $0x1, %bl
cmpb $0x0, 0x4(%r15)
jne 0x9074
xorl %eax, %eax
cmpq $0x22, %rax
je 0x90b7
leaq 0x1(%rax), %rcx
cmpb $0x0, 0x8(%r15,%rax,4)
movq %rcx, %rax
je 0x9058
cmpq $0x23, %rcx
setb %bl
movq %rbp, %rdi
callq 0x5430
testl %eax, %eax
jne 0x908e
movl %r14d, %eax
orl $0x80, %eax
testb %bl, %bl
cmovel %eax, %r14d
movq 0xaf4b(%rip), %rax      # 0x13fe0
movl 0x4(%rax), %eax
movq 0x28(%rsp), %rcx
movl %r14d, (%rcx)
movl %eax, 0x4(%rcx)
xorl %eax, %eax
addq $0x488, %rsp            # imm = 0x488
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbp, %rdi
callq 0x5430
testl %eax, %eax
je 0x911f
testb $0x40, %r14b
jne 0x912b
movl %r14d, %r15d
leaq 0x3ef(%rsp), %r14
leaq 0xa0(%rsp), %rsi
movl $0x69, %edx
movq %r14, %rdi
callq 0x5540
movl %eax, %ebx
testl %eax, %eax
je 0x916c
xorl %ebp, %ebp
jmp 0x918e
movzbl 0x1(%rbx), %ecx
leaq 0x5d3d(%rip), %rsi      # 0xee3e
movl $0x1, %edi
xorl %eax, %eax
callq 0x5949
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
btl $0x8, %r14d
jb 0x908e
jmp 0x90a5
orl $0x80, %r14d
jmp 0x908e
movb $0x1, %al
cmpb $0x0, 0x90(%r15)
jne 0x9158
movl $0x24, %ecx
movq %rcx, %rax
cmpq $0x28, %rcx
je 0x9151
leaq 0x1(%rax), %rcx
cmpb $0x0, 0x4(%r15,%rax,4)
je 0x913c
cmpq $0x28, %rax
setb %al
movl %r14d, %ecx
orl $0x80, %ecx
testb %al, %al
cmovel %ecx, %r14d
jmp 0x908e
xorl %eax, %eax
movq 0x18(%rsp), %rcx
cmpb $0x0, 0xac(%rcx,%rax,4)
setne %bpl
jne 0x918e
leaq 0x1(%rax), %rcx
cmpq $0x4, %rax
movq %rcx, %rax
jne 0x916e
leaq 0x30(%rsp), %rsi
movl $0x69, %edx
movq %r14, %rdi
callq 0x5540
testl %eax, %eax
movl %r15d, %r14d
jne 0x91c5
xorl %ecx, %ecx
movq 0x18(%rsp), %rdx
cmpb $0x0, 0xc0(%rdx,%rcx,4)
jne 0x908e
incq %rcx
cmpq $0x5, %rcx
jne 0x91ae
testb %bpl, %bpl
jne 0x908e
xorl %ecx, %ecx
testl %eax, %eax
sete %cl
xorl %eax, %eax
testl %ebx, %ebx
sete %al
shll $0x4, %eax
orl %r14d, %eax
shll $0x5, %ecx
orl %eax, %ecx
orl $0x80, %ecx
movl %ecx, %r14d
jmp 0x908e
nopl (%rax)