// File: /workspace/github_c_makefile_star2_O2/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 $0x498, %rsp            # imm = 0x498
movq 0xa716(%rip), %r13      # 0x12fe0
movl $0x100, %r12d           # imm = 0x100
movq %rdi, 0x30(%rsp)
andl (%rdi), %r12d
orl (%r13), %r12d
movq %rsi, %r14
xorps %xmm0, %xmm0
movups %xmm0, 0x109(%rsp)
movaps %xmm0, 0x100(%rsp)
movaps %xmm0, 0xf0(%rsp)
movaps %xmm0, 0xe0(%rsp)
movaps %xmm0, 0xd0(%rsp)
movaps %xmm0, 0xc0(%rsp)
movaps %xmm0, 0xb0(%rsp)
movups %xmm0, 0x99(%rsp)
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
pushq $0x12
popq %rsi
movq %r14, %rdi
xorl %edx, %edx
callq 0x50c0
movq %rax, %rdi
callq 0x56b0
movq %rax, %rbx
movq %r14, (%rsp)
movq %r14, %rdi
callq 0x5620
cmpb $0x24, %al
movq %rbx, 0x38(%rsp)
jb 0x8a87
cmpb $0x50, 0x2(%rbx)
jne 0x89c9
addq $0x90, %rbx
pushq $-0x5
popq %r15
leaq 0x40(%rsp), %r14
testq %r15, %r15
je 0x8a5c
leal 0x29(%r15), %eax
movzbl %al, %esi
movq (%rsp), %rdi
callq 0x5060
movq %rax, %rdi
callq 0x5780
movzbl %al, %esi
movq %r14, %rdi
movq %rbx, %rdx
callq 0x87f5
incq %r15
addq $0x15, %r14
addq $0x4, %rbx
jmp 0x898d
movl %r12d, 0x8(%rsp)
pushq $-0x5
popq %rbp
addq $0xc0, %rbx
pushq $0x1
popq %rdx
leaq 0xb0(%rsp), %r14
leaq 0x40(%rsp), %r15
movl %edx, 0x18(%rsp)
movl $0x0, %r12d
testq %rbp, %rbp
je 0x8a62
leal 0x29(%rbp), %eax
movzbl %al, %esi
movq (%rsp), %rdi
movl %edx, 0x10(%rsp)
callq 0x5060
movq %rax, %rdi
callq 0x5780
leaq -0x14(%rbx), %rdx
movzbl %al, %r13d
movq %r14, %rdi
movl %r13d, %esi
callq 0x87f5
testl %eax, %eax
movl 0x18(%rsp), %eax
cmovsl %r12d, %eax
movl %eax, 0x18(%rsp)
movq %r15, %rdi
movl %r13d, %esi
movq %rbx, %rdx
callq 0x87f5
movl 0x10(%rsp), %edx
testl %eax, %eax
cmovsl %r12d, %edx
incq %rbp
addq $0x15, %r14
addq $0x15, %r15
addq $0x4, %rbx
jmp 0x89f2
orl $0x40, %r12d
jmp 0x8a87
movl 0x8(%rsp), %ecx
movl %ecx, %eax
orl $0x10, %eax
cmpl $0x0, 0x18(%rsp)
cmovel %ecx, %eax
movl %eax, %r12d
orl $0x20, %r12d
testl %edx, %edx
cmovel %eax, %r12d
movq 0xa559(%rip), %r13      # 0x12fe0
movl 0x4(%r13), %eax
movl %eax, 0x24(%rsp)
pushq $0x12
popq %rsi
movq (%rsp), %rdi
pushq $0x1
popq %rbp
movl %ebp, %edx
callq 0x50c0
movq %rax, %rbx
leaq 0x120(%rsp), %r14
movl $0x372, %edx            # imm = 0x372
movq %r14, %rdi
xorl %esi, %esi
callq 0x5330
movq %r14, 0x28(%rsp)
movw $0x101, 0x165(%r14)     # imm = 0x101
testq %rbx, %rbx
je 0x8d63
movq %rbx, %rdi
callq 0x56b0
movq %rax, %r13
xorl %eax, %eax
movq %r13, 0x8(%rsp)
cmpq $0x8, %rax
je 0x8c99
movq %rax, %r14
shlq $0x5, %r14
movb 0x2(%r13,%r14), %r15b
testb %r15b, %r15b
je 0x8c91
andb $0xf, %r15b
cmpb $0x5, %r15b
jb 0x8b34
movq %rax, %rbx
pushq $0x1
popq %rdi
leaq 0x5281(%rip), %rsi      # 0xdd9b
callq 0x5960
btl $0x8, %r12d
jae 0x8d4e
xorl %ebp, %ebp
movq %rbx, %rax
jmp 0x8c91
testb %r15b, %r15b
je 0x8b56
movq %rax, 0x10(%rsp)
addq %r13, %r14
movb 0x3(%r14), %al
movb 0x4(%r14), %cl
cmpb $0x12, %al
jne 0x8b6d
cmpb $0x2, %cl
jae 0x8b5d
xorl %eax, %eax
jmp 0x8b6d
xorl %ebp, %ebp
jmp 0x8c91
movl %r12d, %eax
orl $0x1000, %eax           # imm = 0x1000
testl %ebp, %ebp
cmovnel %eax, %r12d
movb $0x12, %al
leaq 0x16(%r14), %rdx
movq %rdx, 0x18(%rsp)
xorl %ebp, %ebp
testb %al, %al
je 0x8c30
cmpb $0x29, %al
jb 0x8b8e
andl $-0xd, %r12d
orl $0x8, %r12d
jmp 0x8bac
cmpb $0x24, %al
jb 0x8ba0
movl %r12d, %edx
andl $0x8, %edx
jne 0x8ba0
orl $0x4, %r12d
jmp 0x8bac
movl %r12d, %edx
orl $0x2, %edx
cmpb $0x12, %al
cmovel %edx, %r12d
movl %r12d, %r13d
movzbl %al, %r12d
movzbl %cl, %ebx
movq (%rsp), %rdi
movl %r12d, %esi
movl %ebx, %edx
callq 0x50c0
testq %rax, %rax
je 0x8c3e
leal -0x1(%r12), %eax
imulq $0x15, %rax, %rax
addq %rsp, %rax
addq $0x120, %rax            # imm = 0x120
cmpb $0x0, (%rbx,%rax)
jne 0x8c65
addq %rbx, %rax
movb $0x1, (%rax)
movq (%rsp), %rdi
movl %r12d, %esi
movl %ebx, %edx
callq 0x50c0
movq %rax, %rdi
callq 0x56b0
leaq 0x1(%rax), %rcx
movb (%rax), %al
cmpb $0x4, %r15b
jne 0x8c26
testb %al, %al
jne 0x8c26
testl %ebp, %ebp
movl %r13d, %r12d
jne 0x8c29
movb 0x15(%r14), %al
movq 0x18(%rsp), %rcx
pushq $0x1
popq %rbp
jmp 0x8c29
movl %r13d, %r12d
movb (%rcx), %cl
jmp 0x8b78
movq 0x8(%rsp), %r13
xorl %ebp, %ebp
movq 0x10(%rsp), %rax
jmp 0x8c91
xorl %ebp, %ebp
pushq $0x1
popq %rdi
leaq 0x5180(%rip), %rsi      # 0xddca
movl %r12d, %edx
movl %ebx, %ecx
xorl %eax, %eax
callq 0x598d
movl %r13d, %r12d
btl $0x8, %r13d
movq 0x8(%rsp), %r13
jmp 0x8c86
pushq $0x1
popq %rdi
leaq 0x5192(%rip), %rsi      # 0xde01
callq 0x5960
movl %r13d, %r12d
btl $0x8, %r13d
movq 0x8(%rsp), %r13
movl $0x0, %ebp
movq 0x10(%rsp), %rax
jae 0x8d4e
incq %rax
jmp 0x8ae4
movb (%r13), %al
movl $0x0, %ebx
testb %al, %al
je 0x8ac9
movzbl 0x1(%r13), %edx
movzbl %al, %esi
movq (%rsp), %rdi
callq 0x50c0
movq %rax, %rbx
movb (%r13), %al
movzbl %al, %edx
testq %rbx, %rbx
je 0x8ea3
imulq $0x15, %rdx, %rcx
movzbl 0x1(%r13), %edx
leaq 0x120(%rsp), %rsi
addq %rsi, %rcx
cmpb $0x0, -0x15(%rdx,%rcx)
je 0x8d03
pushq $0x1
popq %rdi
leaq 0x510e(%rip), %rsi      # 0xde01
callq 0x5960
btl $0x8, %r12d
jae 0x8d4e
movb (%r13), %al
cmpb $0x29, %al
jb 0x8d11
andl $-0xd, %r12d
orl $0x8, %r12d
jmp 0x8d2d
cmpb $0x24, %al
jb 0x8d23
movl %r12d, %ecx
andl $0x8, %ecx
jne 0x8d23
orl $0x4, %r12d
jmp 0x8d2d
xorl %ecx, %ecx
cmpb $0x12, %al
setne %cl
orl %ecx, %r12d
movzbl %al, %eax
imulq $0x15, %rax, %rax
movzbl 0x1(%r13), %ecx
leaq 0x120(%rsp), %rdx
addq %rdx, %rax
movb $0x1, -0x15(%rcx,%rax)
jmp 0x8ac9
pushq $-0x1
popq %rax
addq $0x498, %rsp            # imm = 0x498
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testb $0x10, %r12b
je 0x8d8d
leaq 0x3ff(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
pushq $0x69
popq %rdx
callq 0x5570
movl %r12d, %ecx
andl $-0x11, %ecx
testl %eax, %eax
cmovnel %ecx, %r12d
testb $0x20, %r12b
je 0x8db4
leaq 0x3ff(%rsp), %rdi
leaq 0x40(%rsp), %rsi
pushq $0x69
popq %rdx
callq 0x5570
movl %r12d, %ecx
andl $-0x21, %ecx
testl %eax, %eax
cmovnel %ecx, %r12d
testb $0x40, %r12b
je 0x8ddb
leaq 0x3ff(%rsp), %rdi
leaq 0x40(%rsp), %rsi
pushq $0x69
popq %rdx
callq 0x5570
movl %r12d, %ecx
andl $-0x41, %ecx
testl %eax, %eax
cmovnel %ecx, %r12d
movq (%rsp), %r14
movb $0x1, %bpl
movq 0x38(%rsp), %r15
movzbl %bpl, %ebx
movq %r14, %rdi
callq 0x5460
xorl %ecx, %ecx
testl %eax, %eax
setne %cl
leal (%rcx,%rcx,4), %eax
addl $0x24, %eax
cmpl %ebx, %eax
jbe 0x8f7c
movq %r14, %rdi
movl %ebx, %esi
callq 0x5060
movq %rax, %rdi
callq 0x5780
movzbl %al, %eax
xorl %ecx, %ecx
movq 0x28(%rsp), %rdx
cmpq %rcx, %rax
je 0x8e35
cmpb $0x0, (%rdx,%rcx)
leaq 0x1(%rcx), %rcx
jne 0x8e24
jmp 0x8e47
incb %bpl
addq $0x15, %rdx
movq %rdx, 0x28(%rsp)
movq (%rsp), %r14
jmp 0x8de7
pushq $0x1
popq %rax
movq %rax, %rbx
cmpq $0x24, %rax
je 0x8e5e
leaq 0x1(%rbx), %rax
cmpb $0x0, (%r15,%rbx,4)
je 0x8e4a
movq (%rsp), %rdi
callq 0x5460
testl %eax, %eax
je 0x8ecc
cmpq $0x24, %rbx
jb 0x8f7c
testb $0x40, %r12b
jne 0x8ee1
leaq 0x3ff(%rsp), %r14
leaq 0xb0(%rsp), %rsi
pushq $0x69
popq %rdx
movq %r14, %rdi
callq 0x5570
movl %eax, %ebx
testl %eax, %eax
je 0x8f0b
xorl %ebp, %ebp
jmp 0x8f28
movzbl 0x1(%r13), %ecx
leaq 0x4f8f(%rip), %rsi      # 0xde3e
pushq $0x1
popq %rdi
xorl %eax, %eax
callq 0x598d
btl $0x8, %r12d
pushq $-0x1
popq %rax
jae 0x8d51
jmp 0x8f7c
movl %r12d, %eax
orl $0x80, %eax
cmpq $0x24, %rbx
cmovael %eax, %r12d
jmp 0x8f7c
pushq $0x24
popq %rcx
movq %rcx, %rax
cmpq $0x29, %rcx
je 0x8ef8
leaq 0x1(%rax), %rcx
cmpb $0x0, (%r15,%rax,4)
je 0x8ee4
movl %r12d, %ecx
orl $0x80, %ecx
cmpq $0x29, %rax
cmovael %ecx, %r12d
jmp 0x8f7c
xorl %eax, %eax
movq %r15, %rcx
cmpq $0x5, %rax
setne %bpl
je 0x8f28
cmpb $0x0, 0xac(%rcx,%rax,4)
leaq 0x1(%rax), %rax
je 0x8f10
leaq 0x40(%rsp), %rsi
pushq $0x69
popq %rdx
movq %r14, %rdi
callq 0x5570
testl %eax, %eax
je 0x8f65
testb %bpl, %bpl
jne 0x8f7c
xorl %ecx, %ecx
testl %eax, %eax
sete %cl
xorl %eax, %eax
testl %ebx, %ebx
sete %al
shll $0x4, %eax
orl %r12d, %eax
shll $0x5, %ecx
orl %eax, %ecx
orl $0x80, %ecx
movl %ecx, %r12d
jmp 0x8f7c
xorl %ecx, %ecx
cmpq $0x5, %rcx
je 0x8f3c
cmpb $0x0, 0xc0(%r15,%rcx,4)
leaq 0x1(%rcx), %rcx
je 0x8f67
movq 0x30(%rsp), %rax
movl %r12d, (%rax)
movl 0x24(%rsp), %ecx
movl %ecx, 0x4(%rax)
xorl %eax, %eax
jmp 0x8d51
nop