// File: Ciaxur[P]yagb-emu/src/CPU.cc
// Function: CPU::CPU(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
CPU::CPU(std::string ROMPath): memory(ROMPath) {
  // Default Values
  cyclesLeft = 114;
  extraCycles = 0;
  halted = false;
  running = true;

  // Timer Cycles Initial State
  timerCycles.div = 0;
  timerCycles.tima = 0;

  // CPU Initial State
  IME = false;
  PC = 0x0100;
  SP = 0xFFFE;

  // Register Init
  //reg.A = 0x01; // Default for commercial roms
  reg.A = 0x11;   // Default for test roms
  reg.B = 0x00;
  reg.C = 0x13;
  reg.D = 0x00;
  reg.E = 0xD8;
  reg.F = 0xB0;
  reg.H = 0x01;
  reg.L = 0x4D;

  // Initialize the Opcode & Prefix Map
  this->initOpcodes(this);
  this->initPrefixed(this);

  ppu = new PPU(this, &this->memory);

  // Give memory access to LCD Mode
  this->memory.LCDMode = &(ppu->LCDMode);

  // Memory Power Up Sequence Init Values
  this->memory.memory[0xFF10] = 0x80; // NR10
  this->memory.memory[0xFF11] = 0xBF; // NR11
  this->memory.memory[0xFF12] = 0xF3; // NR12
  this->memory.memory[0xFF14] = 0xBF; // NR14
  this->memory.memory[0xFF16] = 0x3F; // NR21
  this->memory.memory[0xFF17] = 0x00; // NR22
  this->memory.memory[0xFF19] = 0xBF; // NR24
  this->memory.memory[0xFF1A] = 0x7F; // NR30
  this->memory.memory[0xFF1B] = 0xFF; // NR31
  this->memory.memory[0xFF1C] = 0x9F; // NR32
  this->memory.memory[0xFF1E] = 0xBF; // NR34
  this->memory.memory[0xFF20] = 0xFF; // NR41
  this->memory.memory[0xFF21] = 0x00; // NR42
  this->memory.memory[0xFF22] = 0x00; // NR43
  this->memory.memory[0xFF23] = 0xBF; // NR44
  this->memory.memory[0xFF24] = 0x77; // NR50
  this->memory.memory[0xFF25] = 0xF3; // NR51
  this->memory.memory[0xFF26] = 0xF1; // NR52 (Gameboy = 0xF1)
  this->memory.memory[0xFF40] = 0x91; // LCDC
  this->memory.memory[0xFF47] = 0xFC; // BGP
  this->memory.memory[0xFF48] = 0xFF; // OBP0
  this->memory.memory[0xFF49] = 0xFF; // OBP1
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rsi, -0x50(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x58(%rbp)
addq $0x10, %rdi
movq %rdi, -0x78(%rbp)
callq 0xb3f40
movq -0x58(%rbp), %rdi
movq $0x0, 0x60(%rdi)
movq $0x0, 0x68(%rdi)
addq $0x70, %rdi
movq %rdi, -0x70(%rbp)
callq 0xb3f60
movq -0x58(%rbp), %rdi
addq $0xa8, %rdi
movq %rdi, -0x68(%rbp)
callq 0xb3f80
movq -0x58(%rbp), %rdi
addq $0xe0, %rdi
movq %rdi, -0x60(%rbp)
callq 0xb3f80
movq -0x58(%rbp), %rax
movq -0x50(%rbp), %rsi
addq $0x130, %rax            # imm = 0x130
movq %rax, -0x48(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xd120
jmp 0x4a252
movq -0x48(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xbba90
jmp 0x4a261
leaq -0x30(%rbp), %rdi
callq 0xd730
movq -0x58(%rbp), %rdi
addq $0x10158, %rdi          # imm = 0x10158
movq %rdi, -0x80(%rbp)
callq 0xd200
jmp 0x4a280
movq -0x58(%rbp), %rdi
movl $0x72, 0x8(%rdi)
movl $0x0, 0xc(%rdi)
movb $0x0, 0x12a(%rdi)
movb $0x1, 0x12b(%rdi)
movl $0x0, 0x120(%rdi)
movl $0x0, 0x124(%rdi)
movb $0x0, 0x128(%rdi)
movw $0x100, 0x12c(%rdi)     # imm = 0x100
movw $0xfffe, 0x12e(%rdi)    # imm = 0xFFFE
movb $0x11, 0x118(%rdi)
movb $0x0, 0x119(%rdi)
movb $0x13, 0x11a(%rdi)
movb $0x0, 0x11b(%rdi)
movb $-0x28, 0x11c(%rdi)
movb $-0x50, 0x11d(%rdi)
movb $0x1, 0x11e(%rdi)
movb $0x4d, 0x11f(%rdi)
callq 0xe400
jmp 0x4a30c
movq -0x58(%rbp), %rdi
callq 0x2b790
jmp 0x4a317
movl $0x28, %edi
callq 0xd160
movq %rax, -0x88(%rbp)
jmp 0x4a32a
movq -0x58(%rbp), %rsi
movq -0x88(%rbp), %rdi
movq %rsi, %rdx
addq $0x130, %rdx            # imm = 0x130
callq 0xbd000
jmp 0x4a346
movq -0x58(%rbp), %rax
movq -0x88(%rbp), %rcx
movq %rcx, (%rax)
movq (%rax), %rcx
movq %rcx, 0x10150(%rax)
movb $-0x80, 0x10060(%rax)
movb $-0x41, 0x10061(%rax)
movb $-0xd, 0x10062(%rax)
movb $-0x41, 0x10064(%rax)
movb $0x3f, 0x10066(%rax)
movb $0x0, 0x10067(%rax)
movb $-0x41, 0x10069(%rax)
movb $0x7f, 0x1006a(%rax)
movb $-0x1, 0x1006b(%rax)
movb $-0x61, 0x1006c(%rax)
movb $-0x41, 0x1006e(%rax)
movb $-0x1, 0x10070(%rax)
movb $0x0, 0x10071(%rax)
movb $0x0, 0x10072(%rax)
movb $-0x41, 0x10073(%rax)
movb $0x77, 0x10074(%rax)
movb $-0xd, 0x10075(%rax)
movb $-0xf, 0x10076(%rax)
movb $-0x6f, 0x10090(%rax)
movb $-0x4, 0x10097(%rax)
movb $-0x1, 0x10098(%rax)
movb $-0x1, 0x10099(%rax)
addq $0x90, %rsp
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x4a471
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xd730
jmp 0x4a471
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x4a468
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x4a45f
movq -0x88(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
movl $0x28, %esi
callq 0xd100
movq -0x80(%rbp), %rdi
callq 0xd780
movq -0x48(%rbp), %rdi
callq 0xb3fa0
movq -0x60(%rbp), %rdi
callq 0xb3fc0
movq -0x68(%rbp), %rdi
callq 0xb3fc0
movq -0x70(%rbp), %rdi
callq 0xb3fe0
movq -0x78(%rbp), %rdi
callq 0xb4000
movq -0x38(%rbp), %rdi
callq 0xd620
nop