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

  // 取得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 fcDggInfo = *(const uint *)(wds + 154 + (194 - 94) * 4);
  uint lcbDggInfo = *(const uint *)(wds + 154 + (194 - 94) * 4 + 4);
  if (lcbDggInfo == 0 || fcDggInfo >= ts_size) {
    return false;
  }

  const uchar *OfficeArtContent = ts + fcDggInfo;
  const uchar *blipStore = OfficeArtContent + 16 + *(const uint *)(OfficeArtContent + 12);
  uint lcbBlipStore = *(uint *)(blipStore + 4);
  // printf("lcbBlipStore = %u\n", lcbBlipStore);

  const uchar *rgfb = blipStore + 8;
  char *img_name = (char *)malloc(strlen(file_path) + 16);
  while (rgfb < blipStore + lcbBlipStore) {
    static int counter = 0;
    sprintf(img_name, "%s/%05d", file_path, ++counter);
    ushort recType = *(const ushort *)(rgfb + 2);
    uint recSize = *(const uint *)(rgfb + 4);
    /*
    printf("recType = %04X\n", recType);
    printf("recSize = %u\n", recSize);
    */
    if (recType == 0xF007) {
      uint size = *(const uint *)(rgfb + 28);
      uint foDelay = *(const uint *)(rgfb + 36);
      // printf("size = %u, foDelay = %u\n", size, foDelay);
      if (foDelay < wds_size && foDelay + size <= wds_size) {
        storeBlipBlock(wds + foDelay, img_name, size);
      }
    } else if (0xF018 <= recType && recType <= 0xF117) {
      storeBlipBlock(rgfb, img_name, recSize);
    } else {
      break;
    }
    rgfb += 8 + *(const uint *)(rgfb + 4);
  }
  free(img_name);
  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rdi
leaq 0x2907(%rip), %rsi      # 0x6045
leaq -0x20(%rbp), %rdx
leaq -0x2c(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x3758
movb $0x0, -0x1(%rbp)
jmp 0x3944
movq -0x20(%rbp), %rax
movw 0xa(%rax), %ax
movw %ax, -0x32(%rbp)
movzwl -0x32(%rbp), %eax
andl $0x200, %eax            # imm = 0x200
cmpl $0x200, %eax            # imm = 0x200
sete %al
andb $0x1, %al
movb %al, -0x33(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x80(%rbp)
testb $0x1, -0x33(%rbp)
je 0x3798
leaq 0x28c3(%rip), %rax      # 0x6052
movq %rax, -0x88(%rbp)
jmp 0x37a8
leaq 0x28ba(%rip), %rax      # 0x6059
movq %rax, -0x88(%rbp)
jmp 0x37a8
movq -0x80(%rbp), %rdi
movq -0x88(%rbp), %rsi
leaq -0x28(%rbp), %rdx
leaq -0x30(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x37cd
movb $0x0, -0x1(%rbp)
jmp 0x3944
movq -0x20(%rbp), %rax
movl 0x22a(%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movl 0x22e(%rax), %eax
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
je 0x37f5
movl -0x38(%rbp), %eax
cmpl -0x30(%rbp), %eax
jb 0x37fe
movb $0x0, -0x1(%rbp)
jmp 0x3944
movq -0x28(%rbp), %rax
movl -0x38(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
addq $0x10, %rax
movq -0x48(%rbp), %rcx
movl 0xc(%rcx), %ecx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x54(%rbp)
movq -0x50(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x60(%rbp)
movq -0x18(%rbp), %rdi
callq 0x10a0
movq %rax, %rdi
addq $0x10, %rdi
callq 0x1180
movq %rax, -0x68(%rbp)
movq -0x60(%rbp), %rax
movq -0x50(%rbp), %rcx
movl -0x54(%rbp), %edx
addq %rdx, %rcx
cmpq %rcx, %rax
jae 0x3937
movq -0x68(%rbp), %rdi
movq -0x18(%rbp), %rdx
movl 0x6896(%rip), %ecx      # 0xa10c
addl $0x1, %ecx
movl %ecx, 0x688d(%rip)      # 0xa10c
leaq 0x27da(%rip), %rsi      # 0x6060
movb $0x0, %al
callq 0x1060
movq -0x60(%rbp), %rax
movw 0x2(%rax), %ax
movw %ax, -0x6a(%rbp)
movq -0x60(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x70(%rbp)
movzwl -0x6a(%rbp), %eax
cmpl $0xf007, %eax           # imm = 0xF007
jne 0x38ed
movq -0x60(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0x74(%rbp)
movq -0x60(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, -0x78(%rbp)
movl -0x78(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jae 0x38eb
movl -0x78(%rbp), %eax
addl -0x74(%rbp), %eax
cmpl -0x2c(%rbp), %eax
ja 0x38eb
movq -0x20(%rbp), %rdi
movl -0x78(%rbp), %eax
addq %rax, %rdi
movq -0x68(%rbp), %rsi
movl -0x74(%rbp), %edx
callq 0x3e80
jmp 0x391b
movzwl -0x6a(%rbp), %ecx
movl $0xf018, %eax           # imm = 0xF018
cmpl %ecx, %eax
jg 0x3917
movzwl -0x6a(%rbp), %eax
cmpl $0xf117, %eax           # imm = 0xF117
jg 0x3917
movq -0x60(%rbp), %rdi
movq -0x68(%rbp), %rsi
movl -0x70(%rbp), %edx
callq 0x3e80
jmp 0x3919
jmp 0x3937
jmp 0x391b
movq -0x60(%rbp), %rax
movl 0x4(%rax), %ecx
addl $0x8, %ecx
movq -0x60(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
jmp 0x3851
movq -0x68(%rbp), %rdi
callq 0x1160
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)