// File: donfreiday[P]gb/main.cpp
// Function: imguiDisassembly()
void imguiDisassembly() {
  // Get window dimensions
  ImGui::SetNextWindowSize(
      ImVec2(DISASM_WINDOW_WIDTH, ImGui::GetIO().DisplaySize.y));

  // Position in top left corner
  ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));

  ImGui::Begin("disassembly", nullptr,
               ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);

  // Button to run or pause emulator
  if (ImGui::Button(g_running ? "Pause(r)" : " Run(r) ")) {
    g_scrollDisasmToPC = g_running;
    g_running = !g_running;
  }

  // Button for step. Only works when emulation is paused
  ImGui::SameLine();
  if (ImGui::Button("Step(s)")) {
    if (!g_running) {
      g_stepping = true;
    }
  }

  // Button for jump to PC
  ImGui::SameLine();
  if (ImGui::Button("Goto PC(p)")) {
    g_scrollDisasmToPC = true;
  }

  ImGui::BeginChild("disasm", ImVec2(0.0f, 0.0f));
  ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));

  ImGuiListClipper clipper(0x7FFF, ImGui::GetTextLineHeight());
  u16 index = clipper.DisplayStart * 2;

  while (index < clipper.DisplayEnd * 2) {
    // Is the current index a breakpoint?
    bool breakpoint = g_breakpoints.find(index) != g_breakpoints.end();

    // Clicking a line sets or removes a breakpoint
    ImGui::PushID(index);
    if (ImGui::Selectable("##breakpoint",
                          ImGuiSelectableFlags_SpanAllColumns)) {
      if (breakpoint) {
        g_breakpoints.erase(index);
      } else {
        g_breakpoints.insert(index);
      }
    }
    ImGui::PopID();

    // Color currently executing line
    ImVec4 color;
    if (index == g_cpu.reg.pc) {
      color = ImVec4(1.0f, 0.0f, 1.0f, 1.0f);
    } else {
      color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
    }

    // Mark breakpoints
    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
    ImGui::SameLine();
    if (breakpoint) {
      ImGui::Text("*");
    } else {
      ImGui::Text(" ");
    }
    ImGui::PopStyleVar();

    // This will increment index by size of opcode+operand
    int prevIndex = index;
    disassemble(g_cpu, index);

    // Don't skip the current PC
    if (prevIndex < g_cpu.reg.pc && index > g_cpu.reg.pc) {
      index = g_cpu.reg.pc;
      g_disasm.knownEntryPoints.insert(index);
      color = ImVec4(1.0f, 0.0f, 1.0f, 1.0f);
      disassemble(g_cpu, index);
    }

    // Display current address, opcode, and operand (if any)
    ImGui::SameLine();
    if (g_disasm.operandSize > 0) {
      // One byte operand
      if (g_disasm.operandSize == 1) {
        ImGui::TextColored(color, "%04X:%02X %02X    ", g_disasm.address,
                           g_disasm.opcode, (u8)g_disasm.operand);
      }
      // Two byte operand
      else {
        ImGui::TextColored(color, "%04X:%02X %04X  ", g_disasm.address,
                           g_disasm.opcode, g_disasm.operand);
      }
    }
    // No operand
    else {
      ImGui::TextColored(color, "%04X:%02X       ", g_disasm.address,
                         g_disasm.opcode);
    }

    // Display disassembly
    ImGui::SameLine();
    ImGui::TextColored(color, g_disasm.str.c_str(), g_disasm.operand);
  }

  // Scroll to current PC if warranted
  if (!g_running && g_scrollDisasmToPC) {
    float target = (g_cpu.reg.pc - 20) * ImGui::GetTextLineHeight() * 0.5f;
    if (fabsf(target - ImGui::GetScrollY()) > 20) {
      ImGui::SetScrollY(target);
    }
    g_scrollDisasmToPC = false;
  }

  clipper.End();
  ImGui::PopStyleVar();
  ImGui::EndChild();
  ImGui::End();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
callq 0xca90
movss 0x4(%rax), %xmm1
leaq -0x8(%rbp), %rdi
movss 0x5743(%rip), %xmm0     # 0x5d5a4
callq 0x2d280
leaq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0xe790
leaq -0x10(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
leaq -0x10(%rbp), %rdi
xorl %esi, %esi
callq 0x19450
leaq 0xfd49(%rip), %rdi      # 0x67bdb
xorl %eax, %eax
movl %eax, %esi
movl $0x6, %edx
callq 0xe7e0
testb $0x1, 0x277a3(%rip)     # 0x7f64a
je 0x57eb9
leaq 0xfd37(%rip), %rax      # 0x67be7
movq %rax, -0x100(%rbp)
jmp 0x57ec9
leaq 0xfd30(%rip), %rax      # 0x67bf0
movq %rax, -0x100(%rbp)
jmp 0x57ec9
movq -0x100(%rbp), %rax
movq %rax, -0x108(%rbp)
leaq -0x18(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
movq -0x108(%rbp), %rdi
leaq -0x18(%rbp), %rsi
callq 0x1ad10
testb $0x1, %al
jne 0x57efc
jmp 0x57f1a
movb 0x27748(%rip), %al      # 0x7f64a
andb $0x1, %al
movb %al, 0x27741(%rip)      # 0x7f64b
movb 0x2773a(%rip), %al      # 0x7f64a
xorb $-0x1, %al
andb $0x1, %al
movb %al, 0x27730(%rip)      # 0x7f64a
xorps %xmm0, %xmm0
movss 0x3157(%rip), %xmm1     # 0x5b07c
callq 0x1a5e0
leaq -0x20(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
leaq 0xfcb9(%rip), %rdi      # 0x67bf9
leaq -0x20(%rbp), %rsi
callq 0x1ad10
testb $0x1, %al
jne 0x57f4f
jmp 0x57f61
testb $0x1, 0x276f4(%rip)     # 0x7f64a
jne 0x57f5f
movb $0x1, 0x3f032(%rip)     # 0x96f91
jmp 0x57f61
xorps %xmm0, %xmm0
movss 0x3110(%rip), %xmm1     # 0x5b07c
callq 0x1a5e0
leaq -0x28(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
leaq 0xfc7a(%rip), %rdi      # 0x67c01
leaq -0x28(%rbp), %rsi
callq 0x1ad10
testb $0x1, %al
jne 0x57f96
jmp 0x57f9d
movb $0x1, 0x276ae(%rip)     # 0x7f64b
leaq -0x30(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
leaq 0xfc59(%rip), %rdi      # 0x67c0c
leaq -0x30(%rbp), %rsi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x15bc0
leaq -0x38(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
movl $0x5, %edi
leaq -0x38(%rbp), %rsi
callq 0x18ae0
callq 0x199e0
leaq -0x48(%rbp), %rdi
movl $0x7fff, %esi           # imm = 0x7FFF
callq 0x30090
movl -0x40(%rbp), %eax
shll %eax
movw %ax, -0x4a(%rbp)
movzwl -0x4a(%rbp), %eax
movl -0x3c(%rbp), %ecx
shll %ecx
cmpl %ecx, %eax
jge 0x583c3
leaq 0x3ef4f(%rip), %rdi     # 0x96f60
leaq -0x4a(%rbp), %rsi
callq 0x58d60
movq %rax, -0x110(%rbp)
jmp 0x58023
movq -0x110(%rbp), %rax
movq %rax, -0x58(%rbp)
leaq 0x3ef2b(%rip), %rdi     # 0x96f60
callq 0x58da0
movq %rax, -0x70(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x58d30
movb %al, -0x4b(%rbp)
movzwl -0x4a(%rbp), %edi
callq 0x1cc80
jmp 0x58059
leaq -0x78(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
jmp 0x5806a
leaq 0xfba2(%rip), %rdi      # 0x67c13
movl $0x1, %esi
xorl %edx, %edx
leaq -0x78(%rbp), %rcx
callq 0x27150
movb %al, -0x111(%rbp)
jmp 0x58089
movb -0x111(%rbp), %al
testb $0x1, %al
jne 0x58095
jmp 0x58101
testb $0x1, -0x4b(%rbp)
je 0x580c9
leaq 0x3eebe(%rip), %rdi     # 0x96f60
leaq -0x4a(%rbp), %rsi
callq 0x58e20
jmp 0x580ad
jmp 0x580ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x30150
jmp 0x584c4
leaq 0x3ee90(%rip), %rdi     # 0x96f60
leaq -0x4a(%rbp), %rsi
callq 0x58ce0
movb %dl, -0x121(%rbp)
movq %rax, -0x120(%rbp)
jmp 0x580e8
movb -0x121(%rbp), %al
movq -0x120(%rbp), %rcx
movq %rcx, -0x88(%rbp)
movb %al, -0x80(%rbp)
jmp 0x58101
callq 0x1b550
jmp 0x58108
leaq -0xa0(%rbp), %rdi
callq 0x2d250
jmp 0x58116
movzwl -0x4a(%rbp), %eax
movzwl 0x2bd1f(%rip), %ecx     # 0x83e40
cmpl %ecx, %eax
jne 0x58162
leaq -0xb0(%rbp), %rdi
xorps %xmm1, %xmm1
movss 0x2ee1(%rip), %xmm3     # 0x5b018
movaps %xmm3, %xmm0
movaps %xmm3, %xmm2
callq 0x2d2b0
jmp 0x58144
movq -0xb0(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0x98(%rbp)
jmp 0x5819d
leaq -0xc0(%rbp), %rdi
movss 0x2ea7(%rip), %xmm3     # 0x5b018
movaps %xmm3, %xmm0
movaps %xmm3, %xmm1
movaps %xmm3, %xmm2
callq 0x2d2b0
jmp 0x58181
movq -0xc0(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0xb8(%rbp), %rax
movq %rax, -0x98(%rbp)
leaq -0xc8(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x2d280
jmp 0x581b1
movl $0x7, %edi
leaq -0xc8(%rbp), %rsi
callq 0x18ae0
jmp 0x581c4
xorps %xmm0, %xmm0
movss 0x2ead(%rip), %xmm1     # 0x5b07c
callq 0x1a5e0
jmp 0x581d6
testb $0x1, -0x4b(%rbp)
je 0x581ee
leaq 0x40bf(%rip), %rdi      # 0x5c2a2
xorl %eax, %eax
callq 0x1a220
jmp 0x581ec
jmp 0x58200
leaq 0xfa5e(%rip), %rdi      # 0x67c53
xorl %eax, %eax
callq 0x1a220
jmp 0x581fe
jmp 0x58200
movl $0x1, %edi
callq 0x159f0
jmp 0x5820c
movzwl -0x4a(%rbp), %eax
movl %eax, -0xcc(%rbp)
leaq 0x2bc1b(%rip), %rdi     # 0x83e38
leaq -0x4a(%rbp), %rsi
callq 0x588a0
jmp 0x58228
movl -0xcc(%rbp), %eax
movzwl 0x2bc0b(%rip), %ecx     # 0x83e40
cmpl %ecx, %eax
jge 0x582d5
movzwl -0x4a(%rbp), %eax
movzwl 0x2bbf8(%rip), %ecx     # 0x83e40
cmpl %ecx, %eax
jle 0x582d5
movw 0x2bbe9(%rip), %ax      # 0x83e40
movw %ax, -0x4a(%rbp)
leaq 0x3ecce(%rip), %rdi     # 0x96f30
leaq -0x4a(%rbp), %rsi
callq 0x58ce0
movb %dl, -0x131(%rbp)
movq %rax, -0x130(%rbp)
jmp 0x5827a
movb -0x131(%rbp), %al
movq -0x130(%rbp), %rcx
movq %rcx, -0xe0(%rbp)
movb %al, -0xd8(%rbp)
leaq -0xf0(%rbp), %rdi
xorps %xmm1, %xmm1
movss 0x2d72(%rip), %xmm3     # 0x5b018
movaps %xmm3, %xmm0
movaps %xmm3, %xmm2
callq 0x2d2b0
jmp 0x582b3
movups -0xf0(%rbp), %xmm0
movaps %xmm0, -0xa0(%rbp)
leaq 0x2bb70(%rip), %rdi     # 0x83e38
leaq -0x4a(%rbp), %rsi
callq 0x588a0
jmp 0x582d3
jmp 0x582d5
xorps %xmm0, %xmm0
movss 0x2d9c(%rip), %xmm1     # 0x5b07c
callq 0x1a5e0
jmp 0x582e7
movzbl 0x3ec40(%rip), %eax     # 0x96f2e
cmpl $0x0, %eax
jle 0x5835f
movzbl 0x3ec34(%rip), %eax     # 0x96f2e
cmpl $0x1, %eax
jne 0x5832e
movzwl 0x3ec22(%rip), %edx     # 0x96f28
movzbl 0x3ec1d(%rip), %ecx     # 0x96f2a
movzbl 0x3ec17(%rip), %r8d     # 0x96f2c
leaq 0xf904(%rip), %rsi      # 0x67c20
xorl %eax, %eax
leaq -0xa0(%rbp), %rdi
callq 0x1a300
jmp 0x5832c
jmp 0x5835d
movzwl 0x3ebf3(%rip), %edx     # 0x96f28
movzbl 0x3ebee(%rip), %ecx     # 0x96f2a
movzwl 0x3ebe8(%rip), %r8d     # 0x96f2c
leaq 0xf8e8(%rip), %rsi      # 0x67c33
xorl %eax, %eax
leaq -0xa0(%rbp), %rdi
callq 0x1a300
jmp 0x5835b
jmp 0x5835d
jmp 0x58386
movzwl 0x3ebc2(%rip), %edx     # 0x96f28
movzbl 0x3ebbd(%rip), %ecx     # 0x96f2a
leaq 0xf8d0(%rip), %rsi      # 0x67c44
xorl %eax, %eax
leaq -0xa0(%rbp), %rdi
callq 0x1a300
jmp 0x58384
jmp 0x58386
xorps %xmm0, %xmm0
movss 0x2ceb(%rip), %xmm1     # 0x5b07c
callq 0x1a5e0
jmp 0x58398
leaq 0x3eb69(%rip), %rdi     # 0x96f08
callq 0x70e0
movq %rax, %rsi
movzwl 0x3eb7e(%rip), %edx     # 0x96f2c
xorl %eax, %eax
leaq -0xa0(%rbp), %rdi
callq 0x1a300
jmp 0x583be
jmp 0x57ff9
testb $0x1, 0x27280(%rip)     # 0x7f64a
jne 0x5848d
testb $0x1, 0x27274(%rip)     # 0x7f64b
je 0x5848d
movzwl 0x2ba5c(%rip), %eax     # 0x83e40
addl $-0x14, %eax
cvtsi2ss %eax, %xmm0
movss %xmm0, -0x13c(%rbp)
callq 0x199e0
movss %xmm0, -0x138(%rbp)
jmp 0x58402
movss -0x138(%rbp), %xmm1
movss -0x13c(%rbp), %xmm0
mulss %xmm1, %xmm0
movss 0x2c06(%rip), %xmm1     # 0x5b024
mulss %xmm1, %xmm0
movss %xmm0, -0xf4(%rbp)
movss -0xf4(%rbp), %xmm0
movss %xmm0, -0x144(%rbp)
callq 0x19e30
movss %xmm0, -0x140(%rbp)
jmp 0x58449
movss -0x140(%rbp), %xmm1
movss -0x144(%rbp), %xmm0
subss %xmm1, %xmm0
movaps 0x2cdc(%rip), %xmm1     # 0x5b140
pand %xmm1, %xmm0
movss 0x5164(%rip), %xmm1     # 0x5d5d4
ucomiss %xmm1, %xmm0
jbe 0x58486
movss -0xf4(%rbp), %xmm0
callq 0x19f10
jmp 0x58484
jmp 0x58486
movb $0x0, 0x271be(%rip)     # 0x7f64b
leaq -0x48(%rbp), %rdi
callq 0x300d0
jmp 0x58498
movl $0x1, %edi
callq 0x159f0
jmp 0x584a4
callq 0x15e60
jmp 0x584ab
callq 0xee30
jmp 0x584b2
leaq -0x48(%rbp), %rdi
callq 0x30150
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x74f0
nopl (%rax)