// File: tsfn[P]doc2txt/src/doc_image.cpp
// Function: inline_image(Storage const&, char const*)
static bool inline_image(const Storage &st, const char *file_path) {
  const uchar *wds, *ts, *ds;
  uint wds_size, ts_size, ds_size;

  // 取得Data Stream (ds)
  if (!st.stream("Data", &ds, &ds_size)) {
    return false;
  }

  // 取得WordDocument Stream (wds)
  if (!st.stream("WordDocument", &wds, &wds_size)) {
    return false;
  }

  // 取得Table Stream (ts)
  ushort flag1 = *(ushort *)((char *)wds + 0xA);
  bool is1Table = (flag1 & 0x0200) == 0x0200;
  if (!st.stream(is1Table ? "1Table" : "0Table", &ts, &ts_size)) {
    return false;
  }


  uint fcPlcfBteChpx = *(uint *)(wds + 250);
  uint lcbPlcfBteChpx = *(uint *)(wds + 250 + 4);
  int n = (lcbPlcfBteChpx - 4) / 8;

  for (int i = 0; i < n; ++i) {
    uint PnBteChpx = *(uint *)(ts + fcPlcfBteChpx + 4 * (n + 1 + i));
    const uchar *ChpxFkp = wds + PnBteChpx * 512;
    uchar crun = *(const uchar *)(ChpxFkp + 511);

    for (uint i = 0; i < crun; ++i) {
      // rgfc确定文本的位置
      uint rgfc_start = *(const uint *)(ChpxFkp + 4 * i);
      ushort ch = *(const ushort *)(wds + rgfc_start);
      if (ch != 0x0001) {
        continue;
      }

      // bOffset找到ChpxInFkp在ChpxFkp中的位置
      uchar bOffset = *(const uchar *)(ChpxFkp + 4 * (crun + 1) + 1 * i);
      if (bOffset == 0) {
        continue;
      }

      // 找到ChpxInFkp其中的lcb, grpprlInChpx
      uchar lcb = *(const uchar *)(ChpxFkp + bOffset * 2);
      const uchar *grpprl = ChpxFkp + 2 * bOffset + 1;
      static const int operand_size[8] = { 1, 1, 2, 4, 2, 2, -1, 3, };
      for (uint i = 0; i < lcb;) {
        ushort sprm = *(ushort *)(grpprl + i);
        uint spra = sprm / 8192;
        uint operand;
        i += 2;
        if (spra == 6) {
          i += 1 + *(const uchar *)(grpprl + i);
        } else {
          if (operand_size[spra] == 1) {
            operand = *(const uchar *)(grpprl + i);
          } else if (operand_size[spra] == 2) {
            operand = *(const ushort *)(grpprl + i);
          } else if (operand_size[spra] == 3) {
            operand = *(const uint *)(grpprl + i) & 0x00FFFFFF;
          } else if (operand_size[spra] == 4) {
            operand = *(const uint *)(grpprl + i);
          } else {
            operand = -1;
          }
          i += operand_size[spra];
        }

        if (sprm != 0x6A03) {
          continue;
        }

        const uchar *PICF = ds + operand;
        uint lcbPICF = *(const uint *)PICF;

        ushort picf_mfpf_mm = *(const ushort *)(PICF + 6);
        const uchar *picture = PICF + 68 + (picf_mfpf_mm == 0x0066 ? 1 + *(PICF + 68) : 0);
        const uchar *rgfb = picture + 8 + *(const uint *)(picture + 4);

        char *img_name = (char *)malloc(strlen(file_path) + 16);
        while (PICF <= rgfb && rgfb < PICF + lcbPICF) {
          static int counter = 0;
          sprintf(img_name, "%s/i%05d", file_path, ++counter);
          uint recSize = *(const uint *)(rgfb + 4);
          uchar cbName = *(rgfb + 41);
          storeBlipBlock(rgfb + 44, img_name, recSize - cbName - 36);
          rgfb += 8 + recSize;
        }
        free(img_name);
      }
    }
  }
  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rdi
leaq 0x2733(%rip), %rsi      # 0x60b1
leaq -0x30(%rbp), %rdx
leaq -0x3c(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x3998
movb $0x0, -0x1(%rbp)
jmp 0x3e69
movq -0x10(%rbp), %rdi
leaq 0x26a2(%rip), %rsi      # 0x6045
leaq -0x20(%rbp), %rdx
leaq -0x34(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x39bd
movb $0x0, -0x1(%rbp)
jmp 0x3e69
movq -0x20(%rbp), %rax
movw 0xa(%rax), %ax
movw %ax, -0x3e(%rbp)
movzwl -0x3e(%rbp), %eax
andl $0x200, %eax            # imm = 0x200
cmpl $0x200, %eax            # imm = 0x200
sete %al
andb $0x1, %al
movb %al, -0x3f(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xc0(%rbp)
testb $0x1, -0x3f(%rbp)
je 0x3a00
leaq 0x265b(%rip), %rax      # 0x6052
movq %rax, -0xc8(%rbp)
jmp 0x3a10
leaq 0x2652(%rip), %rax      # 0x6059
movq %rax, -0xc8(%rbp)
jmp 0x3a10
movq -0xc0(%rbp), %rdi
movq -0xc8(%rbp), %rsi
leaq -0x28(%rbp), %rdx
leaq -0x38(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x3a38
movb $0x0, -0x1(%rbp)
jmp 0x3e69
movq -0x20(%rbp), %rax
movl 0xfa(%rax), %eax
movl %eax, -0x44(%rbp)
movq -0x20(%rbp), %rax
movl 0xfe(%rax), %eax
movl %eax, -0x48(%rbp)
movl -0x48(%rbp), %eax
subl $0x4, %eax
shrl $0x3, %eax
movl %eax, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
movl -0x50(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0x3e65
movq -0x28(%rbp), %rax
movl -0x44(%rbp), %ecx
addq %rcx, %rax
movl -0x4c(%rbp), %ecx
addl $0x1, %ecx
addl -0x50(%rbp), %ecx
shll $0x2, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx), %eax
movl %eax, -0x54(%rbp)
movq -0x20(%rbp), %rax
movl -0x54(%rbp), %ecx
shll $0x9, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movb 0x1ff(%rax), %al
movb %al, -0x61(%rbp)
movl $0x0, -0x68(%rbp)
movl -0x68(%rbp), %eax
movzbl -0x61(%rbp), %ecx
cmpl %ecx, %eax
jae 0x3e55
movq -0x60(%rbp), %rax
movl -0x68(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl (%rax,%rcx), %eax
movl %eax, -0x6c(%rbp)
movq -0x20(%rbp), %rax
movl -0x6c(%rbp), %ecx
movw (%rax,%rcx), %ax
movw %ax, -0x6e(%rbp)
movzwl -0x6e(%rbp), %eax
cmpl $0x1, %eax
je 0x3af5
jmp 0x3e47
movq -0x60(%rbp), %rax
movzbl -0x61(%rbp), %ecx
addl $0x1, %ecx
shll $0x2, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movl -0x68(%rbp), %ecx
shll $0x0, %ecx
movl %ecx, %ecx
movb (%rax,%rcx), %al
movb %al, -0x6f(%rbp)
movzbl -0x6f(%rbp), %eax
cmpl $0x0, %eax
jne 0x3b25
jmp 0x3e47
movq -0x60(%rbp), %rax
movzbl -0x6f(%rbp), %ecx
shll %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0x70(%rbp)
movq -0x60(%rbp), %rax
movzbl -0x6f(%rbp), %ecx
shll %ecx
movslq %ecx, %rcx
addq %rcx, %rax
addq $0x1, %rax
movq %rax, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
movzbl -0x70(%rbp), %ecx
cmpl %ecx, %eax
jae 0x3e45
movq -0x78(%rbp), %rax
movl -0x7c(%rbp), %ecx
movw (%rax,%rcx), %ax
movw %ax, -0x7e(%rbp)
movzwl -0x7e(%rbp), %eax
movl $0x2000, %ecx           # imm = 0x2000
cltd
idivl %ecx
movl %eax, -0x84(%rbp)
movl -0x7c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x7c(%rbp)
cmpl $0x6, -0x84(%rbp)
jne 0x3bb2
movq -0x78(%rbp), %rax
movl -0x7c(%rbp), %ecx
movzbl (%rax,%rcx), %eax
addl $0x1, %eax
addl -0x7c(%rbp), %eax
movl %eax, -0x7c(%rbp)
jmp 0x3c80
movl -0x84(%rbp), %eax
movl %eax, %ecx
leaq 0x24ff(%rip), %rax      # 0x60c0
cmpl $0x1, (%rax,%rcx,4)
jne 0x3bdd
movq -0x78(%rbp), %rax
movl -0x7c(%rbp), %ecx
movzbl (%rax,%rcx), %eax
movl %eax, -0x88(%rbp)
jmp 0x3c68
movl -0x84(%rbp), %eax
movl %eax, %ecx
leaq 0x24d4(%rip), %rax      # 0x60c0
cmpl $0x2, (%rax,%rcx,4)
jne 0x3c05
movq -0x78(%rbp), %rax
movl -0x7c(%rbp), %ecx
movzwl (%rax,%rcx), %eax
movl %eax, -0x88(%rbp)
jmp 0x3c66
movl -0x84(%rbp), %eax
movl %eax, %ecx
leaq 0x24ac(%rip), %rax      # 0x60c0
cmpl $0x3, (%rax,%rcx,4)
jne 0x3c31
movq -0x78(%rbp), %rax
movl -0x7c(%rbp), %ecx
movl (%rax,%rcx), %eax
andl $0xffffff, %eax         # imm = 0xFFFFFF
movl %eax, -0x88(%rbp)
jmp 0x3c64
movl -0x84(%rbp), %eax
movl %eax, %ecx
leaq 0x2480(%rip), %rax      # 0x60c0
cmpl $0x4, (%rax,%rcx,4)
jne 0x3c58
movq -0x78(%rbp), %rax
movl -0x7c(%rbp), %ecx
movl (%rax,%rcx), %eax
movl %eax, -0x88(%rbp)
jmp 0x3c62
movl $0xffffffff, -0x88(%rbp) # imm = 0xFFFFFFFF
jmp 0x3c64
jmp 0x3c66
jmp 0x3c68
movl -0x84(%rbp), %eax
movl %eax, %ecx
leaq 0x2449(%rip), %rax      # 0x60c0
movl (%rax,%rcx,4), %eax
addl -0x7c(%rbp), %eax
movl %eax, -0x7c(%rbp)
movzwl -0x7e(%rbp), %eax
cmpl $0x6a03, %eax           # imm = 0x6A03
je 0x3c90
jmp 0x3b57
movq -0x30(%rbp), %rax
movl -0x88(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x94(%rbp)
movq -0x90(%rbp), %rax
movw 0x6(%rax), %ax
movw %ax, -0x96(%rbp)
movq -0x90(%rbp), %rax
addq $0x44, %rax
movq %rax, -0xd0(%rbp)
movzwl -0x96(%rbp), %eax
cmpl $0x66, %eax
jne 0x3cf9
movq -0x90(%rbp), %rax
movzbl 0x44(%rax), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x3d03
xorl %eax, %eax
movl %eax, -0xd4(%rbp)
jmp 0x3d03
movq -0xd0(%rbp), %rax
movl -0xd4(%rbp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
addq $0x8, %rax
movq -0xa0(%rbp), %rcx
movl 0x4(%rcx), %ecx
addq %rcx, %rax
movq %rax, -0xa8(%rbp)
movq -0x18(%rbp), %rdi
callq 0x10a0
movq %rax, %rdi
addq $0x10, %rdi
callq 0x1180
movq %rax, -0xb0(%rbp)
movq -0x90(%rbp), %rcx
xorl %eax, %eax
cmpq -0xa8(%rbp), %rcx
movb %al, -0xd5(%rbp)
ja 0x3d93
movq -0xa8(%rbp), %rax
movq -0x90(%rbp), %rcx
movl -0x94(%rbp), %edx
addq %rdx, %rcx
cmpq %rcx, %rax
setb %al
movb %al, -0xd5(%rbp)
movb -0xd5(%rbp), %al
testb $0x1, %al
jne 0x3da2
jmp 0x3e34
movq -0xb0(%rbp), %rdi
movq -0x18(%rbp), %rdx
movl 0x635d(%rip), %ecx      # 0xa110
addl $0x1, %ecx
movl %ecx, 0x6354(%rip)      # 0xa110
leaq 0x22f3(%rip), %rsi      # 0x60b6
movb $0x0, %al
callq 0x1060
movq -0xa8(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0xb4(%rbp)
movq -0xa8(%rbp), %rax
movb 0x29(%rax), %al
movb %al, -0xb5(%rbp)
movq -0xa8(%rbp), %rdi
addq $0x2c, %rdi
movq -0xb0(%rbp), %rsi
movl -0xb4(%rbp), %edx
movzbl -0xb5(%rbp), %eax
subl %eax, %edx
subl $0x24, %edx
callq 0x3e80
movl -0xb4(%rbp), %ecx
addl $0x8, %ecx
movq -0xa8(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0xa8(%rbp)
jmp 0x3d58
movq -0xb0(%rbp), %rdi
callq 0x1160
jmp 0x3b57
jmp 0x3e47
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x3ab7
jmp 0x3e57
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x3a65
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xe0, %rsp
popq %rbp
retq
nopw (%rax,%rax)