// File: /workspace/github_cpp_makefile_star2_O1/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 0x21cf2
cmpl $-0x1, %eax
je 0x22149
leaq 0x10(%r13), %rdi
movq %rbx, %rsi
callq 0xb900
movq (%r13), %r14
movq 0x2622e(%rip), %r15     # 0x47ff0
leaq 0x13753(%rip), %rsi     # 0x3551c
movl $0xe, %edx
movq %r15, %rdi
callq 0xb7a0
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq %r15, %rdi
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
leaq 0x13728(%rip), %rsi     # 0x3552c
movl $0xb, %edx
movq %r15, %rdi
callq 0xb7a0
movzbl 0x4(%r14), %esi
movq %r15, %rdi
callq 0xb290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
leaq 0x136dc(%rip), %rsi     # 0x3552b
movl $0xc, %edx
movq %r15, %rdi
callq 0xb7a0
movzbl 0x5(%r14), %esi
movq %r15, %rdi
callq 0xb290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
leaq 0x1369e(%rip), %rsi     # 0x35538
movl $0xb, %edx
movq %r15, %rdi
callq 0xb7a0
movzbl 0x8(%r14), %esi
movq %r15, %rdi
callq 0xb290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
movq %r14, -0x30(%rbp)
testb $0x4, 0x6(%r14)
je 0x21f24
leaq 0x13654(%rip), %rsi     # 0x35544
movl $0xf, %edx
movq %r15, %rdi
callq 0xb7a0
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq %r15, %rdi
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
movq -0x30(%rbp), %r12
movzbl 0x6(%r12), %eax
shrl $0x4, %eax
movzbl 0x7(%r12), %ebx
andl $-0x10, %ebx
orl %eax, %ebx
movq 0x260ad(%rip), %r15     # 0x47ff0
leaq 0x13666(%rip), %rsi     # 0x355b0
movl $0x8, %edx
movq %r15, %rdi
callq 0xb7a0
movq %r15, %rdi
movl %ebx, -0x34(%rbp)
movl %ebx, %esi
callq 0xb290
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq %rbx, %rdi
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
xorl %eax, %eax
movq %rax, -0x70(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -0x80(%rbp)
movq %rax, -0x50(%rbp)
movaps %xmm0, -0x60(%rbp)
movq (%r13), %r14
addq $0x10, %r14
movb 0x4(%r12), %al
testb %al, %al
je 0x22045
movq %r13, -0x88(%rbp)
xorl %ebx, %ebx
leaq 0x1358c(%rip), %r12     # 0x35554
movq %r14, %r13
movl $0x14, %edx
movq %r15, %rdi
movq %r12, %rsi
callq 0xb7a0
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq %r15, %rdi
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
movq %r13, -0x40(%rbp)
movq -0x78(%rbp), %rsi
cmpq -0x70(%rbp), %rsi
je 0x2201a
movq %r13, (%rsi)
addq $0x8, -0x78(%rbp)
jmp 0x22027
leaq -0x80(%rbp), %rdi
leaq -0x40(%rbp), %rdx
callq 0x22718
incq %rbx
movq -0x30(%rbp), %rax
movzbl 0x4(%rax), %eax
addq $0x4000, %r13           # imm = 0x4000
cmpq %rax, %rbx
jb 0x21fcb
movq -0x88(%rbp), %r13
movq -0x30(%rbp), %rcx
cmpb $0x0, 0x5(%rcx)
je 0x2209d
movzbl %al, %eax
shll $0xe, %eax
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 0x2207b
movq %r14, (%rsi)
addq $0x8, -0x58(%rbp)
jmp 0x22086
movq %rbx, %rdi
movq %r15, %rdx
callq 0x22718
incq %r12
movq -0x30(%rbp), %rax
movzbl 0x5(%rax), %eax
addq $0x2000, %r14           # imm = 0x2000
cmpq %rax, %r12
jb 0x22063
movq -0x30(%rbp), %rax
movb 0x6(%rax), %r12b
movl -0x34(%rbp), %eax
testb %al, %al
je 0x221d4
movzbl %al, %eax
cmpl $0x1, %eax
je 0x22153
cmpl $0x4, %eax
jne 0x222b7
movq 0x25ecc(%rip), %rbx     # 0x47f98
leaq 0x134be(%rip), %rsi     # 0x35591
movl $0x12, %edx
movq %rbx, %rdi
callq 0xb7a0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq 0x25e9a(%rip), %rdi     # 0x47f98
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
movl $0x60, %edi
callq 0xb130
movq %rax, %r15
andb $0x1, %r12b
movq -0x30(%rbp), %rax
movzbl 0x8(%rax), %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 0x233d8
jmp 0x22247
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x222a8
movq 0x25e3e(%rip), %rbx     # 0x47f98
leaq 0x1341d(%rip), %rsi     # 0x3557e
movl $0x12, %edx
movq %rbx, %rdi
callq 0xb7a0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq 0x25e0c(%rip), %rdi     # 0x47f98
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
movl $0x58, %edi
callq 0xb130
movq %rax, %r15
andb $0x1, %r12b
movq -0x30(%rbp), %rax
movzbl 0x8(%rax), %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 0x22e80
jmp 0x22247
movq 0x25dbd(%rip), %rbx     # 0x47f98
leaq 0x13387(%rip), %rsi     # 0x35569
movl $0x14, %edx
movq %rbx, %rdi
callq 0xb7a0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0xb850
movsbl %al, %esi
movq 0x25d8b(%rip), %rdi     # 0x47f98
callq 0xb410
movq %rax, %rdi
callq 0xb3c0
movl $0x40, %edi
callq 0xb130
movq %rax, %r15
andb $0x1, %r12b
movq -0x30(%rbp), %rax
movzbl 0x8(%rax), %ecx
movzbl %r12b, %r8d
leaq -0x80(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movq %r15, %rdi
callq 0x22bdc
movq 0x80(%r13), %rdi
movq %r15, 0x80(%r13)
testq %rdi, %rdi
je 0x22260
movq (%rdi), %rax
callq *0x8(%rax)
movq 0x70(%r13), %rax
movq 0x80(%r13), %rcx
movq %rcx, (%rax)
movq 0x78(%r13), %rax
movq 0x80(%r13), %rcx
movq %rcx, (%rax)
movq -0x60(%rbp), %rdi
testq %rdi, %rdi
je 0x22291
movq -0x50(%rbp), %rsi
subq %rdi, %rsi
callq 0xb0e0
movq -0x80(%rbp), %rdi
testq %rdi, %rdi
je 0x222a6
movq -0x70(%rbp), %rsi
subq %rdi, %rsi
callq 0xb0e0
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x25cda(%rip), %rbx     # 0x47f98
leaq 0x132df(%rip), %rsi     # 0x355a4
movl $0x14, %edx
movq %rbx, %rdi
callq 0xb7a0
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 -0x34(%rbp), %eax
movb %al, (%rsi)
movl $0x1, %edx
movq %rbx, %rdi
callq 0xb7a0
movq %rax, %rdi
callq 0xb800
leaq 0x12198(%rip), %rdi     # 0x344a4
leaq 0x1316c(%rip), %rsi     # 0x3547f
leaq 0x1329f(%rip), %rcx     # 0x355b9
movl $0x174, %edx            # imm = 0x174
callq 0xb160
movq %rax, %rbx
movl $0x60, %esi
jmp 0x22340
movq %rax, %rbx
movl $0x40, %esi
jmp 0x22340
movq %rax, %rbx
movl $0x58, %esi
movq %r15, %rdi
callq 0xb0e0
jmp 0x22359
jmp 0x22356
jmp 0x22356
jmp 0x22356
jmp 0x22356
jmp 0x22356
jmp 0x22356
movq %rax, %rbx
movq -0x60(%rbp), %rdi
testq %rdi, %rdi
je 0x2236e
movq -0x50(%rbp), %rsi
subq %rdi, %rsi
callq 0xb0e0
movq -0x80(%rbp), %rdi
testq %rdi, %rdi
je 0x22383
movq -0x70(%rbp), %rsi
subq %rdi, %rsi
callq 0xb0e0
movq %rbx, %rdi
callq 0xb4d0
nop