// File: /workspace/github_cpp_makefile_star2_O3/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 0x4400
movq (%r14), %rsi
movq %r15, %rdi
movl $0xc, %edx
callq 0x4240
movq 0x10(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x30(%rsp,%rax)
jne 0x998a
leaq 0x88(%rsp), %rdi
callq 0x40e0
testb %al, %al
je 0x998a
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x4480
leaq 0x10(%rsp), %rdi
callq 0x45f0
movl %eax, 0x8c(%rbx)
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x4480
cmpl $0x100, 0x8c(%rbx)      # imm = 0x100
jl 0x998a
leaq 0x10(%rbx), %r14
leaq 0xf(%rsp), %rdx
movb $0x0, (%rdx)
movl $0x80, %esi
movq %r14, %rdi
callq 0xa08e
movq (%r14), %rsi
leaq 0x10(%rsp), %rdi
movl $0x80, %edx
callq 0x4450
movq 0x1280c(%rip), %rdi     # 0x1bfb0
leaq 0xacef(%rip), %rsi      # 0x1449a
movl $0x8, %edx
callq 0x4410
leaq 0xace7(%rip), %r15      # 0x144a3
xorl %r12d, %r12d
movq (%r14), %rax
movzbl (%rax,%r12), %esi
movq %r15, %rdi
xorl %eax, %eax
callq 0x4050
incq %r12
cmpq $0x20, %r12
jne 0x97bf
movq 0x127cf(%rip), %rdi     # 0x1bfb0
leaq 0xacc2(%rip), %rsi      # 0x144aa
movl $0x9, %edx
callq 0x4410
leaq 0xacbb(%rip), %r15      # 0x144b4
xorl %r12d, %r12d
movq (%r14), %rax
movzbl (%rax,%r12), %esi
movq %r15, %rdi
xorl %eax, %eax
callq 0x4050
incq %r12
cmpq $0x20, %r12
jne 0x97fc
movq 0x12792(%rip), %r15     # 0x1bfb0
leaq 0xac85(%rip), %rsi      # 0x144aa
movl $0x9, %edx
movq %r15, %rdi
callq 0x4410
leaq 0xac81(%rip), %r12      # 0x144ba
leaq 0xac6f(%rip), %r13      # 0x144af
xorl %ebp, %ebp
movq (%r14), %rax
movzbl (%rax,%rbp), %esi
leal -0x20(%rsi), %eax
cmpb $0x5e, %al
ja 0x985c
movq %r12, %rdi
xorl %eax, %eax
callq 0x4050
jmp 0x9866
movq %r13, %rdi
xorl %eax, %eax
callq 0x4050
incq %rbp
cmpq $0x20, %rbp
jne 0x9842
movq (%r15), %rax
addq -0x18(%rax), %r15
movq %r15, %rdi
movl $0xa, %esi
callq 0x4390
movsbl %al, %esi
movq 0x12723(%rip), %r15     # 0x1bfb0
movq %r15, %rdi
callq 0x4030
movq %rax, %rdi
callq 0x4290
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 0x995f
movb $0x45, %cl
cmpb $0x53, 0x2(%rax)
jne 0x995f
cmpb $0x4d, 0x3(%rax)
jne 0x995f
cmpb $0x1a, 0x4(%rax)
jne 0x995f
movzbl 0x5(%rax), %esi
cmpl $0x1, %esi
jne 0x99b4
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 0x99c4
andb $0x1, %al
movl %eax, %ecx
xorb $0x1, %cl
movb %al, 0xcc(%rbx)
movb %cl, 0xcd(%rbx)
testb %al, %al
je 0x99cd
leaq 0xaefc(%rip), %rdi      # 0x14854
callq 0x4540
jmp 0x9994
movzbl %cl, %edx
movzbl 0x2(%rax), %ecx
movzbl 0x3(%rax), %r8d
movzbl 0x4(%rax), %r9d
leaq 0xabc0(%rip), %rdi      # 0x14537
xorl %eax, %eax
callq 0x4050
leaq 0xaf0c(%rip), %rdi      # 0x14891
callq 0x4540
leaq 0x10(%rsp), %rdi
callq 0x40c0
xorl %ebp, %ebp
leaq 0x10(%rsp), %rdi
callq 0x40f0
movl %ebp, %eax
addq $0x218, %rsp            # imm = 0x218
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xaba2(%rip), %rdi      # 0x1455d
xorl %eax, %eax
callq 0x4050
jmp 0x998a
movw $0x101, 0xcc(%rbx)      # imm = 0x101
movb $0x0, 0xcf(%rbx)
movl $0x38, %edi
callq 0x43b0
movq %rax, %r14
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1369c
movq %r14, (%rbx)
movq 0x10(%rbx), %rax
xorl %ecx, %ecx
cmpb $0x0, 0x70(%rax,%rcx)
je 0x9a03
movb $0x1, 0xcf(%rbx)
incq %rcx
cmpq $0x8, %rcx
jne 0x99f5
cmpb $0x0, 0xcf(%rbx)
je 0x9b35
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 0x45e0
movq %rax, %r14
leaq 0xa6f0(%rip), %rsi      # 0x14138
movl $0x1, %edx
movq %rax, %rdi
callq 0x4410
movl 0x8c(%rbx), %esi
addl $-0x80, %esi
movq %r14, %rdi
callq 0x45e0
movq %rax, %r14
leaq 0xaa42(%rip), %rsi      # 0x144b2
movl $0x1, %edx
movq %rax, %rdi
callq 0x4410
movl 0x8c(%rbx), %eax
leal 0xfff(%rax), %esi
testl %eax, %eax
cmovnsl %eax, %esi
sarl $0xc, %esi
movq %r14, %rdi
callq 0x45e0
movl 0x8c(%rbx), %esi
leal 0xfff(%rsi), %ecx
testl %esi, %esi
cmovnsl %esi, %ecx
andl $0xfffff000, %ecx       # imm = 0xFFFFF000
subl %ecx, %esi
movq %rax, %rdi
callq 0x45e0
movq %rax, %rdi
callq 0x41d0
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 0xa08e
xorl %r14d, %r14d
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
cmpq $0x8, %r14
jne 0x9b02
addl $0x8000, 0xb8(%rbx)     # imm = 0x8000
jmp 0x9b4b
leaq 0x28(%rbx), %rdi
leaq 0xf(%rsp), %rdx
movb $0x0, (%rdx)
movl $0x8000, %esi           # imm = 0x8000
callq 0xa08e
movq 0x1245e(%rip), %r14     # 0x1bfb0
leaq 0xaa29(%rip), %rsi      # 0x14582
movl $0xb, %edx
movq %r14, %rdi
callq 0x4410
movq (%r14), %rax
movq -0x18(%rax), %rax
movl 0x18(%r14,%rax), %ecx
andl $-0x4b, %ecx
orl $0x2, %ecx
movl %ecx, 0x18(%r14,%rax)
movq 0x30(%rbx), %rsi
subq 0x28(%rbx), %rsi
movq %r14, %rdi
callq 0x4280
movq %rax, %r14
leaq 0xa9f7(%rip), %rsi      # 0x1458e
movl $0x3, %edx
movq %rax, %rdi
callq 0x4410
movq (%r14), %rax
movq -0x18(%rax), %rax
movl 0x18(%r14,%rax), %ecx
andl $-0x4b, %ecx
orl $0x8, %ecx
movl %ecx, 0x18(%r14,%rax)
movq 0x30(%rbx), %rsi
subq 0x28(%rbx), %rsi
movq %r14, %rdi
callq 0x4280
movq %rax, %r14
leaq 0xb8ad(%rip), %rsi      # 0x15482
movl $0x1, %edx
movq %rax, %rdi
callq 0x4410
movq %r14, %rdi
callq 0x41d0
leaq 0x40(%rbx), %r14
movq 0x30(%rbx), %rsi
subq 0x28(%rbx), %rsi
movq %r14, %rdi
callq 0xa0e8
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 0x4450
movq 0x28(%rbx), %rax
movq %rax, %rcx
notq %rcx
addq 0x30(%rbx), %rcx
je 0x9c61
movq (%r14), %rdx
xorl %esi, %esi
movzbl (%rax,%rsi), %edi
leaq 0x1(%rsi), %r8
movl %r8d, %r9d
movzbl (%rax,%r9), %r10d
shll $0x8, %r10d
orl %edi, %r10d
movl %r10d, (%rdx,%rsi,4)
movq %r8, %rsi
cmpq %r9, %rcx
ja 0x9c3e
movl $0x0, 0x88(%rbx)
leaq 0x58(%rbx), %rdi
leaq 0xf(%rsp), %rdx
movb $0x0, (%rdx)
movl $0x2000, %esi           # imm = 0x2000
callq 0xa08e
leaq 0x10(%rsp), %rdi
callq 0x40c0
movb $0x1, %bpl
movb %bpl, 0xce(%rbx)
movb %bpl, 0xa0(%rbx)
jmp 0x9996
jmp 0x9cbc
jmp 0x9cbc
jmp 0x9cbc
movq %rax, %rbx
movq %r14, %rdi
callq 0x4380
jmp 0x9cbf
jmp 0x9cbc
jmp 0x9cbc
jmp 0x9cbc
jmp 0x9cbc
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x40f0
movq %rbx, %rdi
callq 0x4610
nop