// File: /workspace/github_c_makefile_star2_O0/jsummers[P]deark/modules/fat.c
// Function: do_boot_sector
static int do_boot_sector(deark *c, lctx *d, i64 pos1)
{
	i64 pos;
	i64 num_data_region_sectors;
	i64 num_root_dir_sectors;
	i64 num_sectors_per_fat16;
	i64 num_sectors_per_fat32 = 0;
	i64 num_sectors16;
	i64 num_sectors32 = 0;
	i64 num_sectors_per_track;
	i64 num_heads;
	i64 num_sectors_per_cylinder;
	i64 num_cylinders = 0;
	i64 jmpinstrlen;
	u8 b;
	u8 cksum_sig[2];
	int retval = 0;
	char tmpbuf[16];

	de_dbg(c, "boot sector at %"I64_FMT, pos1);
	de_dbg_indent(c, 1);

	// BIOS parameter block
	jmpinstrlen = (d->subfmt==FAT_SUBFMT_ATARIST)?2:3;
	de_dbg(c, "jump instr: %s",
		de_render_hexbytes_from_dbuf(c->infile, pos1, jmpinstrlen, tmpbuf, sizeof(tmpbuf)));

	if(d->subfmt==FAT_SUBFMT_ATARIST) {
		do_oem_name(c, d, pos1+2, 6);
		de_dbg(c, "serial num: %s",
			de_render_hexbytes_from_dbuf(c->infile, pos1+8, 3, tmpbuf, sizeof(tmpbuf)));
	}
	else {
		do_oem_name(c, d, pos1+3, 8);
	}

	pos = pos1+11;
	d->bytes_per_sector = de_getu16le_p(&pos);
	de_dbg(c, "bytes per sector: %d", (int)d->bytes_per_sector);
	d->sectors_per_cluster = (i64)de_getbyte_p(&pos);
	de_dbg(c, "sectors per cluster: %d", (int)d->sectors_per_cluster);
	d->num_rsvd_sectors = de_getu16le_p(&pos);

	de_dbg(c, "reserved sectors: %d", (int)d->num_rsvd_sectors);
	if(d->num_rsvd_sectors==0) {
		// This happens on some Atari ST disks. Don't know why.
		d->num_rsvd_sectors = 1;
	}

	d->num_fats = (i64)de_getbyte_p(&pos);
	de_dbg(c, "number of FATs: %d", (int)d->num_fats);

	// This is expected to be 0 for FAT32.
	d->max_root_dir_entries16 = de_getu16le_p(&pos);
	de_dbg(c, "max number of root dir entries (if FAT12/16): %d", (int)d->max_root_dir_entries16);

	num_sectors16 = de_getu16le_p(&pos);
	de_dbg(c, "number of sectors (old 16-bit field): %d", (int)num_sectors16);
	b = de_getbyte_p(&pos);
	de_dbg(c, "media descriptor: 0x%02x", (UI)b);
	num_sectors_per_fat16 = de_getu16le_p(&pos);
	de_dbg(c, "sectors per FAT (if FAT12/16): %d", (int)num_sectors_per_fat16);

	num_sectors_per_track = de_getu16le_p(&pos);
	de_dbg(c, "sectors per track: %d", (int)num_sectors_per_track);
	num_heads = de_getu16le_p(&pos);
	de_dbg(c, "number of heads: %d", (int)num_heads);

	pos = pos1+0x1fe;
	de_read(cksum_sig, pos, 2);
	de_dbg(c, "boot sector signature: %s",
		de_render_hexbytes_from_mem(cksum_sig, 2, tmpbuf, sizeof(tmpbuf)));

	do_atarist_boot_checksum(c, d, pos1);
	if(d->has_atarist_checksum) {
		d->platform = FAT_PLATFORM_ATARIST;
		de_dbg(c, "[This is probably a bootable Atari ST disk.]");
	}
	else if(cksum_sig[0]==0x55 && cksum_sig[1]==0xaa) {
		d->platform = FAT_PLATFORM_PC;
		de_dbg(c, "[Disk has PC-compatible boot code.]");
	}

	if(num_sectors16==0) {
		num_sectors32 = de_getu32le(pos1+32);
		de_dbg(c, "num sectors (new 32-bit field): %"I64_FMT, num_sectors32);
	}

	if(num_sectors_per_fat16==0) {
		num_sectors_per_fat32 = de_getu32le(pos1+36);
		de_dbg(c, "sectors per FAT (if FAT32): %u", (UI)num_sectors_per_fat32);
	}

	if(num_sectors_per_fat16==0) {
		d->num_sectors_per_fat = num_sectors_per_fat32;
	}
	else {
		d->num_sectors_per_fat = num_sectors_per_fat16;
	}

	if(num_sectors16==0) {
		d->num_sectors = num_sectors32;
	}
	else {
		d->num_sectors = num_sectors16;
	}

	num_sectors_per_cylinder = num_heads * num_sectors_per_track;
	if(num_sectors_per_cylinder > 0) {
		num_cylinders = de_pad_to_n(d->num_sectors, num_sectors_per_cylinder) / num_sectors_per_cylinder;
	}
	de_dbg(c, "number of cylinders (calculated): %"I64_FMT, num_cylinders);

	if(d->sectors_per_cluster<1) goto done;
	if(d->bytes_per_sector<32) goto done;
	d->bytes_per_cluster = d->bytes_per_sector * d->sectors_per_cluster;
	d->root_dir_sector = d->num_rsvd_sectors + d->num_sectors_per_fat * d->num_fats;
	de_dbg(c, "root dir pos (calculated): %"I64_FMT" (sector %"I64_FMT")",
		sectornum_to_offset(c, d, d->root_dir_sector), d->root_dir_sector);

	// num_root_dir_sectors is expected to be 0 for FAT32.
	num_root_dir_sectors = (d->max_root_dir_entries16*32 + d->bytes_per_sector - 1)/d->bytes_per_sector;

	num_data_region_sectors = d->num_sectors - (d->root_dir_sector + num_root_dir_sectors);
	if(num_data_region_sectors<0) goto done;
	d->num_data_region_clusters = num_data_region_sectors / d->sectors_per_cluster;
	de_dbg(c, "number of clusters (calculated): %"I64_FMT, d->num_data_region_clusters);

	d->data_region_sector = d->root_dir_sector + num_root_dir_sectors;
	d->data_region_pos = d->data_region_sector * d->bytes_per_sector;
	de_dbg(c, "data region pos (calculated): %"I64_FMT" (sector %"I64_FMT")", d->data_region_pos,
		d->data_region_sector);

	// (The first cluster is numbered "2".)
	d->num_cluster_identifiers = d->num_data_region_clusters + 2;

	if(d->num_data_region_clusters < 4085) {
		d->num_fat_bits = 12;
	}
	else if(d->num_data_region_clusters < 65525) {
		d->num_fat_bits = 16;
	}
	else {
		d->num_fat_bits = 32;
	}

	de_dbg(c, "bits per cluster id (calculated): %u", (UI)d->num_fat_bits);

	retval = 1;

done:
	if(!retval) {
		de_err(c, "Invalid or unsupported boot sector");
	}
	de_dbg_indent(c, -1);
	return retval;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq $0x0, -0x40(%rbp)
movq $0x0, -0x50(%rbp)
movq $0x0, -0x70(%rbp)
movl $0x0, -0x80(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rdx
leaq 0x12aea5(%rip), %rsi    # 0x1adf2a
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0x15b560
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edx
movl $0x3, %eax
movl $0x2, %ecx
cmpl $0x2, %edx
cmovel %ecx, %eax
cltq
movq %rax, -0x78(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x18(%rbp), %rsi
movq -0x78(%rbp), %rdx
leaq -0x90(%rbp), %rcx
movl $0x10, %r8d
callq 0x15b6f0
movq -0x98(%rbp), %rdi
movq %rax, %rdx
leaq 0x12ae48(%rip), %rsi    # 0x1adf3d
movb $0x0, %al
callq 0x15b0d0
movq -0x10(%rbp), %rax
cmpl $0x2, 0xc(%rax)
jne 0x8316c
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq $0x2, %rdx
movl $0x6, %ecx
callq 0x83d40
movq -0x8(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x18(%rbp), %rsi
addq $0x8, %rsi
leaq -0x90(%rbp), %rcx
movl $0x3, %edx
movl $0x10, %r8d
callq 0x15b6f0
movq -0xa0(%rbp), %rdi
movq %rax, %rdx
leaq 0x12ade9(%rip), %rsi    # 0x1adf4c
movb $0x0, %al
callq 0x15b0d0
jmp 0x83186
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq $0x3, %rdx
movl $0x8, %ecx
callq 0x83d40
movq -0x18(%rbp), %rax
addq $0xb, %rax
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1652c0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movl %eax, %edx
leaq 0x11bf30(%rip), %rsi    # 0x19f0f3
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x165170
movzbl %al, %eax
movl %eax, %ecx
movq -0x10(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movl %eax, %edx
leaq 0x12ad5e(%rip), %rsi    # 0x1adf5b
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1652c0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x50(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rax
movl %eax, %edx
leaq 0x12ad3e(%rip), %rsi    # 0x1adf73
movb $0x0, %al
callq 0x15b0d0
movq -0x10(%rbp), %rax
cmpq $0x0, 0x50(%rax)
jne 0x83253
movq -0x10(%rbp), %rax
movq $0x1, 0x50(%rax)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x165170
movzbl %al, %eax
movl %eax, %ecx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movl %eax, %edx
leaq 0x12ad02(%rip), %rsi    # 0x1adf88
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1652c0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x68(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x68(%rax), %rax
movl %eax, %edx
leaq 0x12acdd(%rip), %rsi    # 0x1adf9b
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1652c0
movq %rax, -0x48(%rbp)
movq -0x8(%rbp), %rdi
movq -0x48(%rbp), %rax
movl %eax, %edx
leaq 0x12ace1(%rip), %rsi    # 0x1adfcc
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x165170
movb %al, -0x79(%rbp)
movq -0x8(%rbp), %rdi
movzbl -0x79(%rbp), %edx
leaq 0x12ace0(%rip), %rsi    # 0x1adff5
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1652c0
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
movl %eax, %edx
leaq 0x12accc(%rip), %rsi    # 0x1ae00e
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1652c0
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rax
movl %eax, %edx
leaq 0x11bd99(%rip), %rsi    # 0x19f108
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x20(%rbp), %rsi
callq 0x1652c0
movq %rax, -0x60(%rbp)
movq -0x8(%rbp), %rdi
movq -0x60(%rbp), %rax
movl %eax, %edx
leaq 0x11bd82(%rip), %rsi    # 0x19f11e
movb $0x0, %al
callq 0x15b0d0
movq -0x18(%rbp), %rax
addq $0x1fe, %rax            # imm = 0x1FE
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
leaq -0x7b(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl $0x2, %ecx
callq 0x164d10
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
leaq -0x7b(%rbp), %rdi
leaq -0x90(%rbp), %rdx
movl $0x2, %esi
movl $0x10, %ecx
callq 0x15b5c0
movq -0xa8(%rbp), %rdi
movq %rax, %rdx
leaq 0x12ac2f(%rip), %rsi    # 0x1ae030
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x83e10
movq -0x10(%rbp), %rax
cmpb $0x0, 0x15(%rax)
je 0x83442
movq -0x10(%rbp), %rax
movl $0x2, 0x10(%rax)
movq -0x8(%rbp), %rdi
leaq 0x12ac11(%rip), %rsi    # 0x1ae04a
movb $0x0, %al
callq 0x15b0d0
jmp 0x83475
movzbl -0x7b(%rbp), %eax
cmpl $0x55, %eax
jne 0x83473
movzbl -0x7a(%rbp), %eax
cmpl $0xaa, %eax
jne 0x83473
movq -0x10(%rbp), %rax
movl $0x1, 0x10(%rax)
movq -0x8(%rbp), %rdi
leaq 0x12ac0b(%rip), %rsi    # 0x1ae077
movb $0x0, %al
callq 0x15b0d0
jmp 0x83475
cmpq $0x0, -0x48(%rbp)
jne 0x834ab
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
callq 0x165540
movq %rax, -0x50(%rbp)
movq -0x8(%rbp), %rdi
movq -0x50(%rbp), %rdx
leaq 0x12abf7(%rip), %rsi    # 0x1ae09b
movb $0x0, %al
callq 0x15b0d0
cmpq $0x0, -0x38(%rbp)
jne 0x834e3
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x18(%rbp), %rsi
addq $0x24, %rsi
callq 0x165540
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rdi
movq -0x40(%rbp), %rax
movl %eax, %edx
leaq 0x12abe3(%rip), %rsi    # 0x1ae0bf
movb $0x0, %al
callq 0x15b0d0
cmpq $0x0, -0x38(%rbp)
jne 0x834f8
movq -0x40(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x60(%rax)
jmp 0x83504
movq -0x38(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x60(%rax)
cmpq $0x0, -0x48(%rbp)
jne 0x83519
movq -0x50(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
jmp 0x83525
movq -0x48(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x60(%rbp), %rax
imulq -0x58(%rbp), %rax
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
jle 0x83554
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x68(%rbp), %rsi
callq 0x15ce90
cqto
idivq -0x68(%rbp)
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rdi
movq -0x70(%rbp), %rdx
leaq 0x12ab7b(%rip), %rsi    # 0x1ae0de
movb $0x0, %al
callq 0x15b0d0
movq -0x10(%rbp), %rax
cmpq $0x1, 0x20(%rax)
jge 0x8357a
jmp 0x83745
movq -0x10(%rbp), %rax
cmpq $0x20, 0x18(%rax)
jge 0x8358a
jmp 0x83745
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x10(%rbp), %rax
imulq 0x20(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rcx
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq -0x10(%rbp), %rdx
imulq 0x58(%rdx), %rax
addq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x70(%rax)
movq -0x8(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x70(%rax), %rdx
callq 0x83e80
movq -0xb0(%rbp), %rdi
movq %rax, %rdx
movq -0x10(%rbp), %rax
movq 0x70(%rax), %rcx
leaq 0x12ab04(%rip), %rsi    # 0x1ae104
movb $0x0, %al
callq 0x15b0d0
movq -0x10(%rbp), %rax
movq 0x68(%rax), %rax
shlq $0x5, %rax
movq -0x10(%rbp), %rcx
addq 0x18(%rcx), %rax
subq $0x1, %rax
movq -0x10(%rbp), %rcx
cqto
idivq 0x18(%rcx)
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq -0x10(%rbp), %rcx
movq 0x70(%rcx), %rcx
addq -0x30(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jge 0x83654
jmp 0x83745
movq -0x28(%rbp), %rax
movq -0x10(%rbp), %rcx
cqto
idivq 0x20(%rcx)
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x48(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rdx
leaq 0x12aab0(%rip), %rsi    # 0x1ae130
movb $0x0, %al
callq 0x15b0d0
movq -0x10(%rbp), %rax
movq 0x70(%rax), %rcx
addq -0x30(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rcx
movq -0x10(%rbp), %rax
imulq 0x18(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rdx
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rcx
leaq 0x12aa86(%rip), %rsi    # 0x1ae155
movb $0x0, %al
callq 0x15b0d0
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rcx
addq $0x2, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x78(%rax)
movq -0x10(%rbp), %rax
cmpq $0xff5, 0x48(%rax)      # imm = 0xFF5
jge 0x83702
movq -0x10(%rbp), %rax
movb $0xc, 0x14(%rax)
jmp 0x83724
movq -0x10(%rbp), %rax
cmpq $0xfff5, 0x48(%rax)     # imm = 0xFFF5
jge 0x8371a
movq -0x10(%rbp), %rax
movb $0x10, 0x14(%rax)
jmp 0x83722
movq -0x10(%rbp), %rax
movb $0x20, 0x14(%rax)
jmp 0x83724
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movzbl 0x14(%rax), %edx
leaq 0x12aa4d(%rip), %rsi    # 0x1ae184
movb $0x0, %al
callq 0x15b0d0
movl $0x1, -0x80(%rbp)
cmpl $0x0, -0x80(%rbp)
jne 0x8375d
movq -0x8(%rbp), %rdi
leaq 0x12aa53(%rip), %rsi    # 0x1ae1a9
movb $0x0, %al
callq 0x15bfb0
movq -0x8(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x15b560
movl -0x80(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
nopw (%rax,%rax)