// File: /workspace/github_cpp_makefile_star2_O2/khedoros[P]khednes/rom.cpp
// Function: rom::load_nsf(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&)
bool rom::load_nsf(std::string& filename) {
    std::ifstream filein;
    filein.open(filename.c_str(),std::ios::binary|std::ios::in);
    if(!(filein&&filein.is_open())) {
        filein.close();
        return false;
    }
    //get filesize
    filein.seekg(0,std::ios::end);
    filesize=int(filein.tellg());
    filein.seekg(0,std::ios::beg);
    if(filesize<0x100) {
        filein.close();
        return false;
    }
    //parse the header, assign appropriate values to properties
    header.resize(0x80,0);
    filein.read(reinterpret_cast<char*>(&header[0]),0x80);

    std::cout<<"Header: ";
    for(int i=0;i<0x20;++i) {
        printf(" %02x ",header[i]);
    }
    std::cout<<"\n        ";
    for(int i=0;i<0x20;++i) {
        printf("%03d ", header[i]);
    }
    std::cout<<"\n        ";;
    for(int i=0;i<0x20;++i) {
        if(header[i] >= 32 && header[i] < 127)
            printf("  %c ", header[i]);
        else printf("    ");
    }
    std::cout<<std::endl;

    if(header[0]!='N'||header[1]!='E'||header[2]!='S'||header[3]!='M'||header[4]!=0x1a) {
        printf("(%02x)  (%02x)  (%02x)  (%02x) (%02x)", header[0],header[1],header[2],header[3],header[4]);
        printf("Header doesn't match expected NSF header.\n");
        filein.close();
        return false;
    }
    
    if(header[5] != 1) {
        printf("I don't handle files of version %d.\n", header[5]);
        filein.close();
        return false;
    }
    song_count = header[6];

    song_index = header[7] - 1;

    //Find the load addr
    int startl=header[0x08];
    int starth=header[0x09];
    load_addr=startl|starth<<8;

    //Find the song-init/power-on vector
    startl=header[0x0a];
    starth=header[0x0b];
    rst_addr=startl|starth<<8;

    //Find the NMI bit vector/song iteration vector
    startl=header[0x0c];
    starth=header[0x0d];
    nmi_addr=startl|starth<<8;
    //if(get_pword(NM_INT_INSERTION) != nmi_addr) std::cout<<"Unexpected error!"<<std::endl;

    //Ticks for PAL+NTSC in 1uS increments (play speed)
    startl=header[0x6e];
    starth=header[0x6f];
    ntsc_ticks = startl|starth<<8;

    startl=header[0x78];
    starth=header[0x79];
    pal_ticks = startl|starth<<8;

    if(header[0x7a] & 0x2) {
        pal = ntsc = true;
    }
    else {
        pal = (header[0x7a] & 0x1);
        ntsc = !pal;
    }

    if(!ntsc) {
        printf("NTSC not available, and that's all I'm supporting right now.\n");
        return false;
    }

    uses_banks = false;
    map = new mapper_nsf(this);
    for(int i=0;i<8;++i) {
        if(header[0x70+i]) uses_banks = true;
    }

    if(uses_banks) {
        std::cout<<std::hex<<load_addr<<"\t"<<filesize-0x80<<" "<<filesize/0x1000<<filesize % 0x1000<<std::endl;
        load_addr &= 0xfff;
        size_t prom_size = filesize - 0x80 + (load_addr&0xFFF);
        //assert(prom_size > 0 && prom_size + 0x8000 > rst_addr);
        if(prom_size < 0x8000) prom_size = 0x8000;
        prom.resize(prom_size, 0);
        for(int i=0;i<8;++i) {
            map->put_pbyte(0, header[0x70+i], 0x5ff8+i);
        }
        load_addr += 0x8000;
    }
    else {
        size_t prom_size = 0x8000;
        //size_t prom_size = filesize - 0x80 + load_addr;
        //assert(prom_size > 0 && prom_size + 0x8000 > rst_addr);
        prom.resize(prom_size, 0);
        //prom.resize(0x8000,0);
    }
    std::cout<<"PROM size: "<<std::dec<<prom.size()<<"(0x"<<std::hex<<prom.size()<<")"<<std::endl;
    prom_w.resize(prom.size());

    filein.read(reinterpret_cast<char*>(&prom[load_addr-0x8000]),filesize-0x80);
    for(unsigned int i=0;i<prom.size()-1;++i) {
        prom_w[i] = prom[i] | (prom[i+1]<<(8));
    }

    mirror_mode=VERT; //vertical mirrored
    crom.resize(CHR_PAGE_SIZE,0);

    filein.close();

    nsf = true;
    sram = true;

    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x218, %rsp            # imm = 0x218
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x10(%rsp), %r15
movq %r15, %rdi
callq 0x43e0
movq (%r14), %rsi
pushq $0xc
popq %rdx
movq %r15, %rdi
callq 0x4230
movq 0x10(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x30(%rsp,%rax)
jne 0x8965
leaq 0x88(%rsp), %rdi
callq 0x40d0
testb %al, %al
je 0x8965
leaq 0x10(%rsp), %rdi
pushq $0x2
popq %rdx
xorl %esi, %esi
callq 0x4460
leaq 0x10(%rsp), %rdi
callq 0x4620
movl %eax, 0x8c(%rbx)
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x4460
cmpl $0x100, 0x8c(%rbx)      # imm = 0x100
jl 0x8965
leaq 0x10(%rbx), %r14
leaq 0xf(%rsp), %rdx
movb $0x0, (%rdx)
movl $0x80, %esi
movq %r14, %rdi
callq 0x8f6a
movq (%r14), %rsi
leaq 0x10(%rsp), %rdi
movl $0x80, %edx
callq 0x4420
movq 0x12808(%rip), %rdi     # 0x1afb0
leaq 0x9ccf(%rip), %rsi      # 0x1247e
callq 0x4390
leaq 0x9ccc(%rip), %r15      # 0x12487
xorl %r12d, %r12d
cmpq $0x20, %r12
je 0x87db
movq (%r14), %rax
movzbl (%rax,%r12), %esi
movq %r15, %rdi
xorl %eax, %eax
callq 0x4040
incq %r12
jmp 0x87be
movq 0x127ce(%rip), %rdi     # 0x1afb0
leaq 0x9ca5(%rip), %rsi      # 0x1248e
callq 0x4390
leaq 0x9ca3(%rip), %r15      # 0x12498
xorl %r12d, %r12d
cmpq $0x20, %r12
je 0x8815
movq (%r14), %rax
movzbl (%rax,%r12), %esi
movq %r15, %rdi
xorl %eax, %eax
callq 0x4040
incq %r12
jmp 0x87f8
movq 0x12794(%rip), %rdi     # 0x1afb0
leaq 0x9c6b(%rip), %rsi      # 0x1248e
callq 0x4390
leaq 0x9c6f(%rip), %r15      # 0x1249e
leaq 0x9c5d(%rip), %r12      # 0x12493
xorl %r13d, %r13d
cmpq $0x20, %r13
je 0x8869
movq (%r14), %rax
movzbl (%rax,%r13), %esi
leal -0x20(%rsi), %eax
cmpb $0x5e, %al
ja 0x885a
movq %r15, %rdi
xorl %eax, %eax
callq 0x4040
jmp 0x8864
movq %r12, %rdi
xorl %eax, %eax
callq 0x4040
incq %r13
jmp 0x8839
movq 0x12740(%rip), %r15     # 0x1afb0
movq %r15, %rdi
callq 0x41c0
movq (%r14), %rax
movzbl (%rax), %esi
movl %esi, %edx
xorb $0x4e, %dl
movb 0x1(%rax), %cl
movl %ecx, %edi
xorb $0x45, %dil
orb %dl, %dil
jne 0x893a
movb $0x45, %cl
cmpb $0x53, 0x2(%rax)
jne 0x893a
cmpb $0x4d, 0x3(%rax)
jne 0x893a
cmpb $0x1a, 0x4(%rax)
jne 0x893a
movzbl 0x5(%rax), %esi
cmpl $0x1, %esi
jne 0x898f
movzbl 0x6(%rax), %ecx
movl %ecx, 0xbc(%rbx)
movzbl 0x7(%rax), %ecx
decl %ecx
movl %ecx, 0xc0(%rbx)
movzwl 0x8(%rax), %ecx
movl %ecx, 0xb8(%rbx)
movzwl 0xa(%rax), %ecx
movl %ecx, 0x94(%rbx)
movzwl 0xc(%rax), %ecx
movl %ecx, 0x98(%rbx)
movzwl 0x6e(%rax), %ecx
movl %ecx, 0xc4(%rbx)
movzwl 0x78(%rax), %ecx
movl %ecx, 0xc8(%rbx)
movb 0x7a(%rax), %al
testb $0x2, %al
jne 0x899f
andb $0x1, %al
movl %eax, %ecx
xorb $0x1, %cl
movb %al, 0xcc(%rbx)
movb %cl, 0xcd(%rbx)
testb %al, %al
je 0x89a8
leaq 0x9f05(%rip), %rdi      # 0x12838
callq 0x4540
jmp 0x896f
movzbl %cl, %edx
movzbl 0x2(%rax), %ecx
movzbl 0x3(%rax), %r8d
movzbl 0x4(%rax), %r9d
leaq 0x9bc9(%rip), %rdi      # 0x1251b
xorl %eax, %eax
callq 0x4040
leaq 0x9f15(%rip), %rdi      # 0x12875
callq 0x4540
leaq 0x10(%rsp), %rdi
callq 0x40b0
xorl %ebp, %ebp
leaq 0x10(%rsp), %rdi
callq 0x40e0
movl %ebp, %eax
addq $0x218, %rsp            # imm = 0x218
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x9bab(%rip), %rdi      # 0x12541
xorl %eax, %eax
callq 0x4040
jmp 0x8965
movw $0x101, 0xcc(%rbx)      # imm = 0x101
movb $0x0, 0xcf(%rbx)
pushq $0x38
popq %rdi
callq 0x43a0
movq %rax, %r14
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1165c
movq %r14, (%rbx)
movq 0x10(%rbx), %rax
xorl %ecx, %ecx
cmpq $0x8, %rcx
je 0x89e7
cmpb $0x0, 0x70(%rax,%rcx)
je 0x89e2
movb $0x1, 0xcf(%rbx)
incq %rcx
jmp 0x89ce
cmpb $0x0, 0xcf(%rbx)
je 0x8ae4
movq (%r15), %rax
movq -0x18(%rax), %rax
movl 0x18(%r15,%rax), %ecx
andl $-0x4b, %ecx
orl $0x8, %ecx
movl %ecx, 0x18(%r15,%rax)
movl 0xb8(%rbx), %esi
movq %r15, %rdi
callq 0x4610
leaq 0x9718(%rip), %rsi      # 0x12138
movq %rax, %rdi
callq 0x4390
movl 0x8c(%rbx), %esi
addl $-0x80, %esi
movq %rax, %rdi
callq 0x4610
leaq 0x9a56(%rip), %rsi      # 0x12496
movq %rax, %rdi
callq 0x4390
movq %rax, %rdi
movl 0x8c(%rbx), %eax
movl $0x1000, %ebp           # imm = 0x1000
cltd
idivl %ebp
movl %eax, %esi
callq 0x4610
movq %rax, %rdi
movl 0x8c(%rbx), %eax
cltd
idivl %ebp
movl %edx, %esi
callq 0x4610
movq %rax, %rdi
callq 0x41c0
movl $0xfff, %eax            # imm = 0xFFF
andl 0xb8(%rbx), %eax
movl %eax, 0xb8(%rbx)
movl 0x8c(%rbx), %ecx
addl %ecx, %eax
addl $-0x80, %eax
cmpl $0x8001, %eax           # imm = 0x8001
movl $0x8000, %ecx           # imm = 0x8000
cmovael %eax, %ecx
movslq %ecx, %rsi
leaq 0x28(%rbx), %rdi
leaq 0xf(%rsp), %rdx
movb $0x0, (%rdx)
callq 0x8f6a
xorl %r14d, %r14d
cmpq $0x8, %r14
je 0x8afc
movq (%rbx), %rdi
movq 0x10(%rbx), %rax
movzbl 0x70(%rax,%r14), %edx
movq (%rdi), %rax
movl %r14d, %ecx
orl $0x5ff8, %ecx           # imm = 0x5FF8
xorl %esi, %esi
callq *0x20(%rax)
incq %r14
jmp 0x8abb
leaq 0x28(%rbx), %rdi
leaq 0xf(%rsp), %rdx
movb $0x0, (%rdx)
movl $0x8000, %esi           # imm = 0x8000
callq 0x8f6a
jmp 0x8b06
addl $0x8000, 0xb8(%rbx)     # imm = 0x8000
movq 0x124a3(%rip), %rdi     # 0x1afb0
leaq 0x9a52(%rip), %rsi      # 0x12566
callq 0x4390
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x2, %edx
movl %edx, 0x18(%rax,%rcx)
movq 0x30(%rbx), %rsi
subq 0x28(%rbx), %rsi
movq %rax, %rdi
callq 0x4270
leaq 0x9a2d(%rip), %rsi      # 0x12572
movq %rax, %rdi
callq 0x4390
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x8, %edx
movl %edx, 0x18(%rax,%rcx)
movq 0x30(%rbx), %rsi
subq 0x28(%rbx), %rsi
movq %rax, %rdi
callq 0x4270
leaq 0xa8b9(%rip), %rsi      # 0x13432
movq %rax, %rdi
callq 0x4390
movq %rax, %rdi
callq 0x41c0
leaq 0x40(%rbx), %rdi
movq 0x30(%rbx), %rsi
subq 0x28(%rbx), %rsi
callq 0x8fc4
movslq 0xb8(%rbx), %rax
movq 0x28(%rbx), %rcx
leaq (%rcx,%rax), %rsi
addq $-0x8000, %rsi          # imm = 0x8000
movslq 0x8c(%rbx), %rdx
addq $-0x80, %rdx
leaq 0x10(%rsp), %rdi
callq 0x4420
movq 0x28(%rbx), %rax
movq 0x40(%rbx), %rcx
movq %rax, %rdx
notq %rdx
addq 0x30(%rbx), %rdx
pushq $0x1
popq %rsi
leal -0x1(%rsi), %edi
cmpq %rdi, %rdx
jbe 0x8bfe
movzbl (%rax,%rdi), %r8d
movl %esi, %r9d
movzbl (%rax,%r9), %r9d
shll $0x8, %r9d
orl %r8d, %r9d
movl %r9d, (%rcx,%rdi,4)
incl %esi
jmp 0x8bda
andl $0x0, 0x88(%rbx)
leaq 0x58(%rbx), %rdi
leaq 0xf(%rsp), %rdx
movb $0x0, (%rdx)
movl $0x2000, %esi           # imm = 0x2000
callq 0x8f6a
leaq 0x10(%rsp), %rdi
callq 0x40b0
movb $0x1, %bpl
movb %bpl, 0xce(%rbx)
movb %bpl, 0xa0(%rbx)
jmp 0x8971
jmp 0x8c56
jmp 0x8c56
jmp 0x8c56
movq %rax, %rbx
movq %r14, %rdi
callq 0x4370
jmp 0x8c59
jmp 0x8c56
jmp 0x8c56
jmp 0x8c56
jmp 0x8c56
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x40e0
movq %rbx, %rdi
callq 0x4640
nop