// File: /workspace/github_c_makefile_star2_O3/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 0x1d70(%rip), %rsi      # 0x8a37
movq %r14, %rdi
callq 0x21a0
testq %rax, %rax
je 0x6ed3
movq %rax, %r15
movq %rax, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x2180
movq %r15, %rdi
callq 0x2030
movq %rax, %r12
movq %r15, %rdi
callq 0x2080
movq %r12, %rdi
callq 0x2200
movq %rax, 0x10018(%rbx)
movl $0x1, %esi
movq %rax, %rdi
movq %r12, %rdx
movq %r15, %rcx
callq 0x2230
cmpq %r12, %rax
jne 0x6ed8
movq %r15, %rdi
callq 0x2170
movl $0x1c, %edi
callq 0x2200
movq %rax, 0x10038(%rbx)
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2628
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 0x1d83(%rip), %rcx      # 0x8afc
movl (%rcx,%rax,4), %esi
movl %esi, 0x10020(%rbx)
leaq 0x1d33(%rip), %rdi      # 0x8abc
xorl %r15d, %r15d
xorl %eax, %eax
callq 0x2050
movb $0x0, 0x10034(%rbx)
movq 0x10038(%rbx), %rax
movzbl 0x13(%rax), %eax
leaq 0x1d74(%rip), %rcx      # 0x8b20
movslq (%rcx,%rax,4), %rdi
movl %edi, 0x10030(%rbx)
cmpl $0x2, %eax
jb 0x6dd3
shlq $0xd, %rdi
movl $0x1, %esi
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 0x6ebd
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 0x1bc5(%rip), %rdx      # 0x8a22
movq %rax, %rdi
movq %r12, %rsi
movq %r14, %rcx
xorl %eax, %eax
callq 0x2250
leaq 0x1bc3(%rip), %rsi      # 0x8a37
movq %r15, %rdi
callq 0x21a0
testq %rax, %rax
je 0x6eb3
movq %rax, %r14
movslq 0x10030(%rbx), %r12
shlq $0xd, %r12
movq 0x10028(%rbx), %rdi
movl $0x1, %esi
movq %r12, %rdx
movq %rax, %rcx
callq 0x2230
cmpq %r12, %rax
jne 0x6ef7
movq %r14, %rdi
callq 0x2170
movq %r15, %rdi
callq 0x21b0
jmp 0x6ec7
movl $0x0, 0x10040(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
callq 0x2290
leaq 0x1b73(%rip), %rdi      # 0x8a52
leaq 0x1ba0(%rip), %rsi      # 0x8a86
leaq 0x1ba6(%rip), %rcx      # 0x8a93
movl $0x8f, %edx
callq 0x20f0
leaq 0x1bc2(%rip), %rdi      # 0x8ac0
leaq 0x1b81(%rip), %rsi      # 0x8a86
leaq 0x1b87(%rip), %rcx      # 0x8a93
movl $0xb7, %edx
callq 0x20f0