// File: /workspace/github_cpp_makefile_star2_O1/khedoros[P]khednes/mapper_001_mmc1.cpp
// Function: mapper_001::put_pbyte(unsigned int, unsigned int, unsigned int)
void mapper_001::put_pbyte(const unsigned int cycle, const unsigned int val,const unsigned int addr) {
    //std::printf("MMC1: %04x = %02x (",addr,val);
    if(val < 128 && mmc1_reg.counter < 4) {
        if(mmc1_reg.counter == 0) {
            //std::cout<<std::endl<<std::endl<<"Initializing new MMC1 register write!"<<std::endl;
        }
        //std::printf("Set temp[%d] to %d\n",mmc1_reg_counter,((val&1)==1?1:0));
        if((val & 1) == 1) {
            mmc1_reg.temp[mmc1_reg.counter]=true;
        }
        else {
            mmc1_reg.temp[mmc1_reg.counter]=false;
        }
        ++(mmc1_reg.counter);
    } else if(val < 128 && mmc1_reg.counter == 4) {
        if(val & 1) {
            mmc1_reg.temp[mmc1_reg.counter]=true;
        }
        else {
            mmc1_reg.temp[mmc1_reg.counter]=false;
        }
        mmc1_reg.counter=0;
        //std::printf("MMC1: %04x = %02x\n",addr,tempval(mmc1_reg.temp));
        //std::cout<<"Setting addr "<<std::hex<<addr<<" to "<<tempval(mmc1_reg.temp)<<std::endl;
        if(addr >= 0x8000 && addr <= 0x9fff) {
            int mirror = mmc1_reg.reg0.mirror;
            int one_screen = mmc1_reg.reg0.obey_mirror;
            mmc1_reg.reg0.val = tempval(mmc1_reg.temp);
            if(mirror != mmc1_reg.reg0.mirror) {
                std::cout<<"Mirror mode changed to "<<!mirror<<"!"<<std::endl;
                if(mmc1_reg.reg0.mirror == 0) ppu_change(cycle, set_vert, 0);
                if(mmc1_reg.reg0.mirror == 1) ppu_change(cycle, set_horiz, 0);
            }
            if(one_screen != mmc1_reg.reg0.obey_mirror) {
                std::cout<<"One-screen mode changed!"<<std::endl;
                if(mmc1_reg.reg0.obey_mirror == 0) ppu_change(cycle, set_4_scr, 0);
                else if(mmc1_reg.reg0.mirror == 0) ppu_change(cycle, set_vert, 0);
                else if(mmc1_reg.reg0.mirror == 1) ppu_change(cycle, set_horiz, 0);
            }
            //std::cout<<"Mirror: "<<(mmc1_reg.reg0.mirror?'H':'V')<<" One-Screen: "<<(!mmc1_reg.reg0.obey_mirror);
            //std::cout<<" PRG Switch: "<<(mmc1_reg.reg0.high_low?'L':'H')<<" PRG Size: "<<(mmc1_reg.reg0.large_small_prg?'S':'L');
            //std::cout<<" CHR Size: "<<(mmc1_reg.reg0.large_small_chr?'S':'L')<<std::endl;
        } else if(addr >= 0xa000 && addr <= 0xbfff) {
            mmc1_reg.reg1.val = tempval(mmc1_reg.temp);
            if(mmc1_reg.reg0.large_small_chr) { //small chr
                cart->updated_crom = 3;
                int new_chr_lo_offset = mmc1_reg.reg1.val * 0x1000;
                int new_chr_hi_offset = mmc1_reg.reg2.val * 0x1000;
                ppu_change(cycle, lo_crom, new_chr_lo_offset);
                ppu_change(cycle, hi_crom, new_chr_hi_offset);
            } else {
                cart->updated_crom = 3;
                int new_chr_lo_offset = mmc1_reg.reg1.val * 0x2000;
                int new_chr_hi_offset = mmc1_reg.reg1.val * 0x2000 + 0x1000;
                ppu_change(cycle, lo_crom, new_chr_lo_offset);
                ppu_change(cycle, hi_crom, new_chr_hi_offset);
            }
            //std::cout<<"CHR ROM bank switching not properly implemented. Sry, dude!"<<std::endl;
        } else if(addr >= 0xc000 && addr <= 0xdfff) {
            mmc1_reg.reg2.val=tempval(mmc1_reg.temp);
            if(mmc1_reg.reg0.large_small_chr) { //small chr
                cart->updated_crom = 3;
                int new_chr_lo_offset = mmc1_reg.reg1.val * 0x1000;
                int new_chr_hi_offset = mmc1_reg.reg2.val * 0x1000;
                ppu_change(cycle, lo_crom, new_chr_lo_offset);
                ppu_change(cycle, hi_crom, new_chr_hi_offset);
            } else {
                cart->updated_crom = 3;
                int new_chr_lo_offset = mmc1_reg.reg1.val * 0x2000;
                int new_chr_hi_offset = mmc1_reg.reg1.val * 0x2000 + 0x1000;
                ppu_change(cycle, lo_crom, new_chr_lo_offset);
                ppu_change(cycle, hi_crom, new_chr_hi_offset);
            }
            //std::cout<<"CHR ROM bank switching not properly implemented. Sry, dude!"<<std::endl;
        } else if(addr >= 0xe000 && addr <= 0xffff) {
            mmc1_reg.reg3.val=tempval(mmc1_reg.temp);
            if(!mmc1_reg.reg0.large_small_prg) { //32KiB switching is "false" value
                int temp = mmc1_reg.reg3.val >>(1);
                prg_lo_offset=temp*0x8000;
                prg_hi_offset=temp*0x8000+PRG_PAGE_SIZE;
            } else if(mmc1_reg.reg0.high_low) { //Switch low PRG
                prg_lo_offset=mmc1_reg.reg3.val*16384;
                prg_hi_offset=(cart->prom_pages -1) * PRG_PAGE_SIZE;
            } else { //Switch high PRG
                prg_lo_offset=0;
                prg_hi_offset=mmc1_reg.reg3.val*16384;
            }
        }
    } else if(val>=128) {
        //std::printf("MMC1: %04x reset\n",addr);
        mmc1_reg.counter=0;
        if(addr>=0x8000&&addr<=0x9fff) {
            //mmc1_reg.reg0.val = 0;
            mmc1_reg.reg0.val |= 0x0C;
            //mmc1_reg.reg0.high_low = 1;
            //mmc1_reg.reg0.large_small_prg = 1;
            //std::cout<<"Clear reg 0"<<std::endl;
        } else if(addr>=0xa000&&addr<=0xbfff) {
            mmc1_reg.reg1.val = 0;
            //std::cout<<"Clear reg 1"<<std::endl;
        } else if(addr>=0xc000&&addr<=0xdfff) {
            mmc1_reg.reg2.val = 0;
            //std::cout<<"Clear reg 2"<<std::endl;
        } else if(addr>=0xe000&&addr<=0xffff) {
            mmc1_reg.reg3.val = 0;
            //std::cout<<"Clear reg 3"<<std::endl;
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rdi, %rbx
cmpl $0x7f, %edx
ja 0x12d98
movl 0x38(%rbx), %eax
cmpq $0x3, %rax
ja 0x12c5c
andb $0x1, %dl
movb %dl, 0x3c(%rbx,%rax)
incl %eax
movl %eax, 0x38(%rbx)
jmp 0x12ddb
cmpl $0x4, %eax
jne 0x12d98
andb $0x1, %dl
movb %dl, 0x40(%rbx)
movl $0x0, 0x38(%rbx)
addl $0xffff8000, %ecx       # imm = 0xFFFF8000
shrl $0xd, %ecx
cmpl $0x3, %ecx
ja 0x12ddb
movl %esi, %ebp
leaq 0x391f(%rip), %rax      # 0x165ac
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movb 0x28(%rbx), %r15b
xorl %eax, %eax
movl $0x40, %edx
movzbl (%rbx,%rdx), %ecx
leal (%rcx,%rax,2), %eax
decq %rdx
cmpq $0x3b, %rdx
jne 0x12ca1
movl %r15d, %r12d
andb $0x1, %r12b
andb $0x1f, %al
movl %r15d, %edx
andb $-0x20, %dl
orb %al, %dl
movb %dl, 0x28(%rbx)
cmpb %r12b, %cl
je 0x12d45
movq 0x92df(%rip), %r14      # 0x1bfb0
leaq 0x38f1(%rip), %rsi      # 0x165c9
movl $0x17, %edx
movq %r14, %rdi
callq 0x4410
xorl %esi, %esi
testb %r12b, %r12b
sete %sil
movq %r14, %rdi
callq 0x45a0
movq %rax, %r14
leaq 0x349a(%rip), %rsi      # 0x1619a
movl $0x1, %edx
movq %rax, %rdi
callq 0x4410
movq %r14, %rdi
callq 0x41d0
testb $0x1, 0x28(%rbx)
jne 0x12d2d
movq (%rbx), %rax
movq %rbx, %rdi
movl %ebp, %esi
movl $0x3, %edx
xorl %ecx, %ecx
callq *0x50(%rax)
testb $0x1, 0x28(%rbx)
je 0x12d45
movq (%rbx), %rax
movq %rbx, %rdi
movl %ebp, %esi
movl $0x2, %edx
xorl %ecx, %ecx
callq *0x50(%rax)
xorb 0x28(%rbx), %r15b
testb $0x2, %r15b
je 0x12ddb
movq 0x9256(%rip), %r14      # 0x1bfb0
leaq 0x3880(%rip), %rsi      # 0x165e1
movl $0x18, %edx
movq %r14, %rdi
callq 0x4410
movq %r14, %rdi
callq 0x41d0
movb 0x28(%rbx), %cl
testb $0x2, %cl
jne 0x12f11
movq (%rbx), %rax
movq 0x50(%rax), %rax
movq %rbx, %rdi
movl %ebp, %esi
movl $0x4, %edx
jmp 0x12f2e
cmpl $0x80, %edx
jb 0x12ddb
movl $0x0, 0x38(%rbx)
addl $0xffff8000, %ecx       # imm = 0xFFFF8000
shrl $0xd, %ecx
cmpl $0x3, %ecx
ja 0x12ddb
leaq 0x37e0(%rip), %rax      # 0x1659c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
orb $0xc, 0x28(%rbx)
jmp 0x12ddb
andb $-0x20, 0x30(%rbx)
jmp 0x12ddb
andb $-0x10, 0x34(%rbx)
jmp 0x12ddb
andb $-0x20, 0x2c(%rbx)
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
xorl %eax, %eax
movl $0x40, %ecx
movzbl (%rbx,%rcx), %edx
leal (%rdx,%rax,2), %eax
decq %rcx
cmpq $0x3b, %rcx
jne 0x12deb
movb 0x30(%rbx), %cl
andb $0x1f, %al
andb $-0x20, %cl
orb %al, %cl
movb %cl, 0x30(%rbx)
jmp 0x12e7a
xorl %edx, %edx
xorl %eax, %eax
movl %eax, %ecx
movzbl 0x40(%rbx,%rdx), %eax
leal (%rax,%rcx,2), %eax
decq %rdx
cmpq $-0x5, %rdx
jne 0x12e0e
movb 0x28(%rbx), %dl
movb 0x34(%rbx), %sil
movl %eax, %edi
andb $0xf, %dil
andb $-0x10, %sil
orb %dil, %sil
movb %sil, 0x34(%rbx)
testb $0x8, %dl
jne 0x12edd
andl $0x7, %ecx
shll $0xf, %ecx
movl %ecx, 0x44(%rbx)
orl $0x4000, %ecx           # imm = 0x4000
movl %ecx, 0x48(%rbx)
jmp 0x12ddb
xorl %eax, %eax
movl $0x40, %ecx
movzbl (%rbx,%rcx), %edx
leal (%rdx,%rax,2), %eax
decq %rcx
cmpq $0x3b, %rcx
jne 0x12e5d
movb 0x2c(%rbx), %cl
andb $0x1f, %al
andb $-0x20, %cl
orb %al, %cl
movb %cl, 0x2c(%rbx)
movb 0x28(%rbx), %al
movq 0x8(%rbx), %rcx
movl $0x3, 0xa4(%rcx)
movzbl 0x2c(%rbx), %ecx
andl $0x1f, %ecx
testb $0x10, %al
jne 0x12ea2
shll $0xd, %ecx
leal 0x1000(%rcx), %r14d
jmp 0x12eb2
shll $0xc, %ecx
movzbl 0x30(%rbx), %r14d
andl $0x1f, %r14d
shll $0xc, %r14d
movq (%rbx), %rax
movq %rbx, %rdi
movl %ebp, %esi
xorl %edx, %edx
callq *0x50(%rax)
movq (%rbx), %rax
movq 0x50(%rax), %rax
movq %rbx, %rdi
movl %ebp, %esi
movl $0x1, %edx
movl %r14d, %ecx
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmpq *%rax
testb $0x4, %dl
jne 0x12ef1
movl $0x0, 0x44(%rbx)
andl $0xf, %eax
shll $0xe, %eax
jmp 0x12f09
andl $0xf, %eax
shll $0xe, %eax
movl %eax, 0x44(%rbx)
movq 0x8(%rbx), %rax
movl 0x78(%rax), %eax
shll $0xe, %eax
addl $0xffffc000, %eax       # imm = 0xFFFFC000
movl %eax, 0x48(%rbx)
jmp 0x12ddb
movq (%rbx), %rax
movq 0x50(%rax), %rax
movq %rbx, %rdi
movl %ebp, %esi
testb $0x1, %cl
jne 0x12f29
movl $0x3, %edx
jmp 0x12f2e
movl $0x2, %edx
xorl %ecx, %ecx
jmp 0x12ed3