// File: mindbeast[P]rnes/main.cpp
// Function: main
int main(int argc, char *argv[]) {
  using namespace std;
  namespace fs = boost::filesystem;
  string romFile;
  bool romFileSpecified = false;

  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  // TODO: convert argument parsing to boost program options
  for (int i = 0; i < argc; i++) {
    if (argv[i] == string("--rom") || argv[i] == string("-r")) {
      romFile = argv[i + 1];
      romFileSpecified = true;
      i += 2;
    }
  }

  if (!romFileSpecified) {
    displayHelpAndQuit();
  }

  try {
    // verify the rom file exists.
    verifyRomExists(romFile);

    auto nes = unique_ptr<Nes>{new Nes{}};
    int res = nes->loadRom(romFile);
    if (res) {
      cerr << "Failed to load rom: " << romFile << endl;
      exit(1);
    }

    // Setup the rnes directories.
    setupDirectories(md5OfFile(romFile));

    // Start the emulator loop.
    nes->run();
  } catch (const fs::filesystem_error &exception) {
    cerr << "Exception: " << exception.what() << endl;
    return -1;
  } catch (const std::exception &exception) {
    cerr << "Exception: " << exception.what() << endl;
    return -1;
  } catch (...) {
    cerr << "Unknown Exception!" << endl;
    return -1;
  }

  google::protobuf::ShutdownProtobufLibrary();
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xe490
movb $0x0, -0x31(%rbp)
leaq 0x4f2ab(%rip), %rdx     # 0x680b8
movl $0x2df5a4, %edi         # imm = 0x2DF5A4
movl $0x2df5a0, %esi         # imm = 0x2DF5A0
callq 0xe1b0
jmp 0x18e1e
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x19046
movq -0x10(%rbp), %rax
movslq -0x48(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x130(%rbp)
leaq -0x69(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0xea50
movq -0x128(%rbp), %rdx
movb $0x0, -0x92(%rbp)
movb $0x0, -0x93(%rbp)
leaq 0x4f251(%rip), %rsi     # 0x680c1
leaq -0x68(%rbp), %rdi
callq 0x19b90
jmp 0x18e7b
movq -0x130(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x1a270
movb %al, -0x131(%rbp)
jmp 0x18e93
movb -0x131(%rbp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x132(%rbp)
jne 0x18f21
jmp 0x18ea8
movq -0x10(%rbp), %rax
movslq -0x48(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x148(%rbp)
leaq -0x91(%rbp), %rdi
movq %rdi, -0x140(%rbp)
callq 0xea50
movq -0x140(%rbp), %rdx
movb $0x1, -0x92(%rbp)
leaq 0x4f1e4(%rip), %rsi     # 0x680c7
leaq -0x90(%rbp), %rdi
callq 0x19b90
jmp 0x18ef1
movq -0x148(%rbp), %rdi
movb $0x1, -0x93(%rbp)
leaq -0x90(%rbp), %rsi
callq 0x1a270
movb %al, -0x149(%rbp)
jmp 0x18f13
movb -0x149(%rbp), %al
movb %al, -0x132(%rbp)
jmp 0x18f21
movb -0x132(%rbp), %al
movb %al, -0x14a(%rbp)
testb $0x1, -0x93(%rbp)
jne 0x18f38
jmp 0x18f44
leaq -0x90(%rbp), %rdi
callq 0xed78
testb $0x1, -0x92(%rbp)
jne 0x18f4f
jmp 0x18f5b
leaq -0x91(%rbp), %rdi
callq 0xed50
leaq -0x68(%rbp), %rdi
callq 0xed78
leaq -0x69(%rbp), %rdi
callq 0xed50
movb -0x14a(%rbp), %al
testb $0x1, %al
jne 0x18f7c
jmp 0x19036
movq -0x10(%rbp), %rax
movslq -0x48(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rsi
leaq -0x30(%rbp), %rdi
callq 0xe500
jmp 0x18f94
movb $0x1, -0x31(%rbp)
movl -0x48(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x48(%rbp)
jmp 0x19036
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1944e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x19028
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1901f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x19006
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
testb $0x1, -0x93(%rbp)
jne 0x18ff8
jmp 0x19004
leaq -0x90(%rbp), %rdi
callq 0xed78
jmp 0x19006
testb $0x1, -0x92(%rbp)
jne 0x19011
jmp 0x1901d
leaq -0x91(%rbp), %rdi
callq 0xed50
jmp 0x1901f
leaq -0x68(%rbp), %rdi
callq 0xed78
leaq -0x69(%rbp), %rdi
callq 0xed50
jmp 0x1944e
jmp 0x19038
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x18e25
testb $0x1, -0x31(%rbp)
jne 0x19055
callq 0x180c0
jmp 0x19053
jmp 0x19055
leaq -0xb8(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xe1a0
jmp 0x19067
leaq -0xb8(%rbp), %rdi
callq 0x187e0
jmp 0x19075
leaq -0xb8(%rbp), %rdi
callq 0xed78
movl $0x88, %edi
callq 0xe200
movq %rax, -0x158(%rbp)
jmp 0x19094
movq -0x158(%rbp), %rdi
callq 0x3d4e0
jmp 0x190a2
movq -0x158(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
movq %rdi, -0x168(%rbp)
callq 0x1a2a0
movq -0x168(%rbp), %rdi
callq 0x1a2d0
movq %rax, %rdi
leaq -0x30(%rbp), %rsi
callq 0x3cd80
movl %eax, -0x15c(%rbp)
jmp 0x190dc
movl -0x15c(%rbp), %eax
movl %eax, -0xc4(%rbp)
cmpl $0x0, -0xc4(%rbp)
je 0x191aa
movq 0x78eec(%rip), %rdi     # 0x91fe8
leaq 0x4efc7(%rip), %rsi     # 0x680ca
callq 0xe680
movq %rax, -0x170(%rbp)
jmp 0x19111
movq -0x170(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xe3e0
movq %rax, -0x178(%rbp)
jmp 0x1912a
movq -0x178(%rbp), %rdi
movq 0x78ea0(%rip), %rsi     # 0x91fd8
callq 0xeae0
jmp 0x1913f
movl $0x1, %edi
callq 0xe730
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x1925c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0xed78
jmp 0x1925c
movq -0x158(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
movl $0x88, %esi
callq 0xe170
jmp 0x1925c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x19250
leaq -0x108(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xe1a0
jmp 0x191bc
leaq -0xe8(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x180f0
jmp 0x191d1
leaq -0xe8(%rbp), %rdi
callq 0x18620
jmp 0x191df
leaq -0xe8(%rbp), %rdi
callq 0xed78
leaq -0x108(%rbp), %rdi
callq 0xed78
leaq -0xc0(%rbp), %rdi
callq 0x1a2d0
movq %rax, %rdi
callq 0x3c820
jmp 0x1920d
leaq -0xc0(%rbp), %rdi
callq 0x1a2f0
jmp 0x19421
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x19244
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0xed78
leaq -0x108(%rbp), %rdi
callq 0xed78
leaq -0xc0(%rbp), %rdi
callq 0x1a2f0
movl -0x44(%rbp), %eax
movl %eax, -0x17c(%rbp)
movl $0x3, %ecx
cmpl %ecx, %eax
jne 0x192f6
movq -0x40(%rbp), %rdi
callq 0xe080
movq %rax, -0x120(%rbp)
movq 0x78d5f(%rip), %rdi     # 0x91fe8
leaq 0x4ee0f(%rip), %rsi     # 0x6809f
callq 0xe680
movq %rax, -0x188(%rbp)
jmp 0x1929e
movq -0x120(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq -0x188(%rbp), %rdi
movq %rax, %rsi
callq 0xe680
movq %rax, -0x190(%rbp)
jmp 0x192c6
movq -0x190(%rbp), %rdi
movq 0x78d04(%rip), %rsi     # 0x91fd8
callq 0xeae0
jmp 0x192db
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x10c(%rbp)
callq 0xe800
jmp 0x1941d
movl -0x17c(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x1938a
movq -0x40(%rbp), %rdi
callq 0xe080
movq %rax, -0x118(%rbp)
movq 0x78cc8(%rip), %rdi     # 0x91fe8
leaq 0x4ed78(%rip), %rsi     # 0x6809f
callq 0xe680
movq %rax, -0x198(%rbp)
jmp 0x19335
movq -0x118(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq -0x198(%rbp), %rdi
movq %rax, %rsi
callq 0xe680
movq %rax, -0x1a0(%rbp)
jmp 0x1935d
movq -0x1a0(%rbp), %rdi
movq 0x78c6d(%rip), %rsi     # 0x91fd8
callq 0xeae0
jmp 0x19372
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x10c(%rbp)
callq 0xe800
jmp 0x19406
movq -0x40(%rbp), %rdi
callq 0xe080
movq 0x78c4e(%rip), %rdi     # 0x91fe8
leaq 0x4ed3e(%rip), %rsi     # 0x680df
callq 0xe680
movq %rax, -0x1a8(%rbp)
jmp 0x193af
movq -0x1a8(%rbp), %rdi
movq 0x78c1b(%rip), %rsi     # 0x91fd8
callq 0xeae0
jmp 0x193c4
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x10c(%rbp)
callq 0xe800
jmp 0x193ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
callq 0xe800
jmp 0x193f1
jmp 0x19439
jmp 0x1944e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
callq 0xe800
jmp 0x19408
jmp 0x19439
jmp 0x1944e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
callq 0xe800
jmp 0x1941f
jmp 0x19439
jmp 0x1944e
callq 0xeb20
jmp 0x19428
movl $0x0, -0x4(%rbp)
movl $0x1, -0x10c(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xed78
movl -0x4(%rbp), %eax
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
leaq -0x30(%rbp), %rdi
callq 0xed78
movq -0x40(%rbp), %rdi
callq 0xe700
movq %rax, %rdi
callq 0x199b0
nopl (%rax,%rax)