// File: /workspace/github_c_makefile_star2_O2/qad114[P]yobeboy/src/memory.c
// Function: MEM_loadROM
void MEM_loadROM(Memory* mem, const char* path) {
    // Open file and get size
    FILE* file = fopen(path, "rb");
    if (file == NULL) {
        perror("Error while opening ROM");
        exit(1);
    }
    fseek(file, 0L, SEEK_END);
    size_t filesize = ftell(file);
    rewind(file);

    // Load ROM into banks array
    mem->romBanks = malloc(filesize); // freed in main.c:quit
    assert(fread(mem->romBanks, 1, filesize, file) == filesize);
    fclose(file);

    // Load cartridge data
    Cartridge* cart = mem->cartridge;
    mem->cartridge = malloc(sizeof(*cart)); // freed in main.c:quit
    CART_init(mem->cartridge, mem);

    // Set fixed bank to bank 0
    mem->romBank0 = mem->romBanks;

    // Set variable bank to 1
    mem->romBankN = mem->romBanks + 0x4000;

    // Set number of banks
    mem->romBanksNo = ((int[]){2, 4, 8, 16, 32, 64, 128, 256, 512})[mem->cartridge->romSize];
    printf("%d\n", mem->romBanksNo);

    // Initialize external RAM
    mem->extRamEnabled = false;
    mem->extRamBanksNo = ((int[]){0, 0, 1, 4, 16, 8})[mem->cartridge->ramSize];

    if (mem->extRamBanksNo != 0) {
        mem->extRamBanks = calloc(0x2000 * mem->extRamBanksNo, 1);
        mem->extRam = mem->extRamBanks + 0;
    } else {
        mem->extRam = NULL;
    }

    // Handle saving if MBC includes battery
    uint8_t mbcCode = mem->romBank0[0x0147];
    if (strchr((const char []){0x03, 0x06, 0x09, 0x0D, 0x0F, 0x10, 0x13, 0x1B, 0x1E, 0x22, '\0'}, mbcCode)) {
        mem->battery = 1;
        mem->romPath = malloc(strlen(path) + 1); // freed in main.c:quit
        strcpy(mem->romPath, path);
        char* saveFileName = malloc(strlen(path) + 5); // freed at the end of this block
        snprintf(saveFileName, strlen(path) + 5, "%s.sav", path);
        FILE* saveFile = fopen(saveFileName, "rb");
        if (saveFile != NULL) {
            filesize = mem->extRamBanksNo * 0x2000;
            assert(fread(mem->extRamBanks, 1, filesize, saveFile) == filesize);
            fclose(saveFile);
        }
        free(saveFileName);

    } else {
        mem->battery = 0;
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x16d0(%rip), %rsi      # 0x7a0f
movq %r14, %rdi
callq 0x21a0
testq %rax, %rax
je 0x653e
movq %rax, %r15
pushq $0x2
popq %rdx
movq %rax, %rdi
xorl %esi, %esi
callq 0x2180
movq %r15, %rdi
callq 0x2030
movq %rax, %r12
movq %r15, %rdi
callq 0x2080
movq %r12, %rdi
callq 0x2200
movq %rax, 0x10018(%rbx)
pushq $0x1
popq %rsi
movq %rax, %rdi
movq %r12, %rdx
movq %r15, %rcx
callq 0x2230
cmpq %r12, %rax
jne 0x6552
movq %r15, %rdi
callq 0x2170
pushq $0x1c
popq %rdi
callq 0x2200
movq %rax, 0x10038(%rbx)
movq %rax, %rdi
movq %rbx, %rsi
callq 0x25ec
movq 0x10018(%rbx), %rax
movq 0x10038(%rbx), %rcx
movq %rax, 0x10000(%rbx)
addq $0x4000, %rax           # imm = 0x4000
movq %rax, 0x10008(%rbx)
movzbl 0x12(%rcx), %eax
leaq 0x16e9(%rip), %rcx      # 0x7ad4
movl (%rcx,%rax,4), %esi
movl %esi, 0x10020(%rbx)
leaq 0x1699(%rip), %rdi      # 0x7a94
xorl %r15d, %r15d
xorl %eax, %eax
callq 0x2050
movb $0x0, 0x10034(%rbx)
movq 0x10038(%rbx), %rax
movzbl 0x13(%rax), %eax
leaq 0x16da(%rip), %rcx      # 0x7af8
movslq (%rcx,%rax,4), %rdi
movl %edi, 0x10030(%rbx)
cmpl $0x2, %eax
jb 0x6443
shlq $0xd, %rdi
pushq $0x1
popq %rsi
callq 0x2100
movq %rax, %r15
movq %rax, 0x10028(%rbx)
movq %r15, 0x10010(%rbx)
movq 0x10000(%rbx), %rax
movzbl 0x147(%rax), %esi
movabsq $0x1b13100f0d090603, %rax # imm = 0x1B13100F0D090603
leaq 0x8(%rsp), %rdi
movq %rax, (%rdi)
movw $0x221e, 0x8(%rdi)      # imm = 0x221E
movb $0x0, 0xa(%rdi)
callq 0x20b0
testq %rax, %rax
je 0x652b
movl $0x1, 0x10040(%rbx)
movq %r14, %rdi
callq 0x20c0
leaq 0x1(%rax), %rdi
callq 0x2200
movq %rax, 0x10048(%rbx)
movq %rax, %rdi
movq %r14, %rsi
callq 0x2150
movq %r14, %rdi
callq 0x20c0
leaq 0x5(%rax), %r12
movq %r12, %rdi
callq 0x2200
movq %rax, %r15
leaq 0x152d(%rip), %rdx      # 0x79fa
movq %rax, %rdi
movq %r12, %rsi
movq %r14, %rcx
xorl %eax, %eax
callq 0x2250
leaq 0x152b(%rip), %rsi      # 0x7a0f
movq %r15, %rdi
callq 0x21a0
testq %rax, %rax
je 0x6521
movq %rax, %r14
movslq 0x10030(%rbx), %r12
shlq $0xd, %r12
movq 0x10028(%rbx), %rdi
pushq $0x1
popq %rsi
movq %r12, %rdx
movq %rax, %rcx
callq 0x2230
cmpq %r12, %rax
jne 0x6571
movq %r14, %rdi
callq 0x2170
movq %r15, %rdi
callq 0x21b0
jmp 0x6532
andl $0x0, 0x10040(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x14cd(%rip), %rdi      # 0x7a12
callq 0x2120
pushq $0x1
popq %rdi
callq 0x21c0
leaq 0x14d1(%rip), %rdi      # 0x7a2a
leaq 0x14fe(%rip), %rsi      # 0x7a5e
leaq 0x1504(%rip), %rcx      # 0x7a6b
movl $0x8f, %edx
callq 0x20f0
leaq 0x1520(%rip), %rdi      # 0x7a98
leaq 0x14df(%rip), %rsi      # 0x7a5e
leaq 0x14e5(%rip), %rcx      # 0x7a6b
movl $0xb7, %edx
callq 0x20f0