// File: /workspace/github_cpp_makefile_star2_O3/mindbeast[P]rnes/nes.cpp
// Function: Rnes::Nes::loadRom(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
int Nes::loadRom(const std::string &filename) {
  int result = mapRom(filename);
  if (result == -1) {
    return -1;
  }
  romFile = filename;
  const NesHeader *header = (const NesHeader *)rom;
  std::cerr << "Loading rom.. " << std::endl;
  std::cerr << "rom banks: " << (int)header->numRomBanks << std::endl;
  std::cerr << "vrom banks: " << (int)header->numVRomBanks << std::endl;
  std::cerr << "ram banks: " << (int)header->numPrgRamBanks << std::endl;
  if (header->info[0] & (1 << 2)) {
    std::cerr << "trainer present" << std::endl;
  }
  uint8_t mapper = (header->info[0] & 0xf0) >> 4;
  mapper |= (header->info[1] & 0xf0);
  std::cerr << "mapper: " << (int)mapper << std::endl;

  std::vector<uint8_t *> prgRoms;
  std::vector<uint8_t *> chrRoms;

  uint8_t *prgRomBase = (uint8_t *)rom + sizeof(NesHeader);
  for (int i = 0; i < header->numRomBanks; i++) {
    std::cerr << "loading rom section " << std::endl;
    uint8_t *prgRom = prgRomBase + i * prgRomSize;
    prgRoms.push_back(prgRom);
  }

  uint8_t *chrRomBase = prgRomBase + header->numRomBanks * prgRomSize;
  for (int i = 0; i < header->numVRomBanks; i++) {
    uint8_t *chrRom = chrRomBase + i * chrRomSize;
    chrRoms.push_back(chrRom);
  }

  bool verticalMirroring = (header->info[0] & 1) != 0;
  switch (mapper) {
  case 0: {
    std::cout << "Loading no mmc game." << std::endl;
    std::unique_ptr<Mmc> mmcLocal(
        new MmcNone(prgRoms, chrRoms, header->numPrgRamBanks, verticalMirroring));
    mmc = std::move(mmcLocal);
    break;
  }
  case 1: {
    std::cout << "Loading MMC1 game." << std::endl;
    std::unique_ptr<Mmc> mmcLocal(new Mmc1(prgRoms, chrRoms, header->numPrgRamBanks,
                                           verticalMirroring, cpuMemory.get(), videoMemory.get()));
    mmc = std::move(mmcLocal);
    break;
  }
  case 4: {
    std::cout << "Loading MMC3 game." << std::endl;
    std::unique_ptr<Mmc> mmcLocal(new Mmc3(prgRoms, chrRoms, header->numPrgRamBanks,
                                           verticalMirroring, cpuMemory.get(), videoMemory.get()));
    mmc = std::move(mmcLocal);
    break;
  }
  default:
    std::cout << "Unsupported mapper: " << std::hex << mapper << std::endl;
    assert(0);
    break;
  }
  cpuMemory->setMmc(mmc.get());
  videoMemory->setMmc(mmc.get());
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, %rbx
movq %rdi, %r13
callq 0x20d20
cmpl $-0x1, %eax
je 0x2116e
leaq 0x10(%r13), %rdi
movq %rbx, %rsi
callq 0xa900
movq (%r13), %r14
movq 0x26200(%rip), %r15     # 0x46ff0
leaq 0x13725(%rip), %rsi     # 0x3451c
movl $0xe, %edx
movq %r15, %rdi
callq 0xa7a0
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq %r15, %rdi
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
leaq 0x136fa(%rip), %rsi     # 0x3452c
movl $0xb, %edx
movq %r15, %rdi
callq 0xa7a0
movzbl 0x4(%r14), %esi
movq %r15, %rdi
callq 0xa290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
leaq 0x136ae(%rip), %rsi     # 0x3452b
movl $0xc, %edx
movq %r15, %rdi
callq 0xa7a0
movzbl 0x5(%r14), %esi
movq %r15, %rdi
callq 0xa290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
leaq 0x13670(%rip), %rsi     # 0x34538
movl $0xb, %edx
movq %r15, %rdi
callq 0xa7a0
movzbl 0x8(%r14), %esi
movq %r15, %rdi
callq 0xa290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
movb 0x6(%r14), %al
testb $0x4, %al
je 0x20f53
leaq 0x13629(%rip), %rsi     # 0x34544
movl $0xf, %edx
movq %r15, %rdi
callq 0xa7a0
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq %r15, %rdi
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
movb 0x6(%r14), %al
movzbl %al, %eax
shrl $0x4, %eax
movzbl 0x7(%r14), %ebx
andl $-0x10, %ebx
orl %eax, %ebx
movq 0x26086(%rip), %r15     # 0x46ff0
leaq 0x1363f(%rip), %rsi     # 0x345b0
movl $0x8, %edx
movq %r15, %rdi
callq 0xa7a0
movq %r15, %rdi
movl %ebx, -0x2c(%rbp)
movl %ebx, %esi
callq 0xa290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
xorl %eax, %eax
movq %rax, -0x70(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -0x80(%rbp)
movq %rax, -0x50(%rbp)
movaps %xmm0, -0x60(%rbp)
movq %r14, %rcx
movq (%r13), %r14
addq $0x10, %r14
movq %rcx, -0x38(%rbp)
cmpb $0x0, 0x4(%rcx)
je 0x21073
movq %r13, -0x88(%rbp)
xorl %ebx, %ebx
leaq 0x13561(%rip), %r12     # 0x34554
movq %r14, %r13
movl $0x14, %edx
movq %r15, %rdi
movq %r12, %rsi
callq 0xa7a0
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq %r15, %rdi
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
movq %r13, -0x40(%rbp)
movq -0x78(%rbp), %rsi
cmpq -0x70(%rbp), %rsi
je 0x21045
movq %r13, (%rsi)
addq $0x8, -0x78(%rbp)
jmp 0x21052
leaq -0x80(%rbp), %rdi
leaq -0x40(%rbp), %rdx
callq 0x21742
incq %rbx
movq -0x38(%rbp), %rax
movzbl 0x4(%rax), %eax
addq $0x4000, %r13           # imm = 0x4000
cmpq %rax, %rbx
jb 0x20ff6
shll $0xe, %eax
movq -0x88(%rbp), %r13
movq -0x38(%rbp), %rcx
cmpb $0x0, 0x5(%rcx)
je 0x210c5
addq %rax, %r14
xorl %r12d, %r12d
leaq -0x60(%rbp), %rbx
leaq -0x40(%rbp), %r15
movq %r14, -0x40(%rbp)
movq -0x58(%rbp), %rsi
cmpq -0x50(%rbp), %rsi
je 0x210a3
movq %r14, (%rsi)
addq $0x8, -0x58(%rbp)
jmp 0x210ae
movq %rbx, %rdi
movq %r15, %rdx
callq 0x21742
incq %r12
movq -0x38(%rbp), %rax
movzbl 0x5(%rax), %eax
addq $0x2000, %r14           # imm = 0x2000
cmpq %rax, %r12
jb 0x2108b
movq -0x38(%rbp), %r14
movb 0x6(%r14), %r12b
movl -0x2c(%rbp), %eax
testb %al, %al
je 0x211f6
movzbl %al, %eax
cmpl $0x1, %eax
je 0x21178
cmpl $0x4, %eax
jne 0x212cf
movq 0x25ea4(%rip), %rbx     # 0x46f98
leaq 0x13496(%rip), %rsi     # 0x34591
movl $0x12, %edx
movq %rbx, %rdi
callq 0xa7a0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq 0x25e72(%rip), %rdi     # 0x46f98
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
movl $0x60, %edi
callq 0xa130
movq %rax, %r15
andb $0x1, %r12b
movzbl 0x8(%r14), %ecx
movq 0x70(%r13), %r9
movq 0x78(%r13), %rax
movq %rax, (%rsp)
movzbl %r12b, %r8d
leaq -0x80(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movq %r15, %rdi
callq 0x223da
jmp 0x21266
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x212c0
movq 0x25e19(%rip), %rbx     # 0x46f98
leaq 0x133f8(%rip), %rsi     # 0x3457e
movl $0x12, %edx
movq %rbx, %rdi
callq 0xa7a0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq 0x25de7(%rip), %rdi     # 0x46f98
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
movl $0x58, %edi
callq 0xa130
movq %rax, %r15
andb $0x1, %r12b
movzbl 0x8(%r14), %ecx
movq 0x70(%r13), %r9
movq 0x78(%r13), %rax
movq %rax, (%rsp)
movzbl %r12b, %r8d
leaq -0x80(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movq %r15, %rdi
callq 0x21eb0
jmp 0x21266
movq 0x25d9b(%rip), %rbx     # 0x46f98
leaq 0x13365(%rip), %rsi     # 0x34569
movl $0x14, %edx
movq %rbx, %rdi
callq 0xa7a0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0xa850
movsbl %al, %esi
movq 0x25d69(%rip), %rdi     # 0x46f98
callq 0xa410
movq %rax, %rdi
callq 0xa3c0
movl $0x40, %edi
callq 0xa130
movq %rax, %r15
andb $0x1, %r12b
movzbl 0x8(%r14), %ecx
movzbl %r12b, %r8d
leaq -0x80(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movq %rax, %rdi
callq 0x21c08
movq 0x80(%r13), %rdi
movq %r15, 0x80(%r13)
testq %rdi, %rdi
je 0x2127f
movq (%rdi), %rax
callq *0x8(%rax)
movq 0x70(%r13), %rax
movq 0x80(%r13), %rcx
movq %rcx, (%rax)
movq 0x78(%r13), %rax
movq %rcx, (%rax)
movq -0x60(%rbp), %rdi
testq %rdi, %rdi
je 0x212a9
movq -0x50(%rbp), %rsi
subq %rdi, %rsi
callq 0xa0e0
movq -0x80(%rbp), %rdi
testq %rdi, %rdi
je 0x212be
movq -0x70(%rbp), %rsi
subq %rdi, %rsi
callq 0xa0e0
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x25cc2(%rip), %rbx     # 0x46f98
leaq 0x132c7(%rip), %rsi     # 0x345a4
movl $0x14, %edx
movq %rbx, %rdi
callq 0xa7a0
movq (%rbx), %rax
movq -0x18(%rax), %rax
movl 0x18(%rbx,%rax), %ecx
andl $-0x4b, %ecx
orl $0x8, %ecx
movl %ecx, 0x18(%rbx,%rax)
leaq -0x40(%rbp), %rsi
movl -0x2c(%rbp), %eax
movb %al, (%rsi)
movl $0x1, %edx
movq %rbx, %rdi
callq 0xa7a0
movq %rax, %rdi
callq 0xa800
leaq 0x12180(%rip), %rdi     # 0x334a4
leaq 0x13154(%rip), %rsi     # 0x3447f
leaq 0x13287(%rip), %rcx     # 0x345b9
movl $0x174, %edx            # imm = 0x174
callq 0xa160
movq %rax, %rbx
movl $0x60, %esi
jmp 0x21358
movq %rax, %rbx
movl $0x40, %esi
jmp 0x21358
movq %rax, %rbx
movl $0x58, %esi
movq %r15, %rdi
callq 0xa0e0
jmp 0x21371
jmp 0x2136e
jmp 0x2136e
jmp 0x2136e
jmp 0x2136e
jmp 0x2136e
jmp 0x2136e
movq %rax, %rbx
movq -0x60(%rbp), %rdi
testq %rdi, %rdi
je 0x21386
movq -0x50(%rbp), %rsi
subq %rdi, %rsi
callq 0xa0e0
movq -0x80(%rbp), %rdi
testq %rdi, %rdi
je 0x2139b
movq -0x70(%rbp), %rsi
subq %rdi, %rsi
callq 0xa0e0
movq %rbx, %rdi
callq 0xa4d0
nop