// File: /workspace/github_cpp_makefile_star2_O2/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 %rbx
pushq %rax
movq %rdi, %rbx
cmpl $0x7f, %edx
ja 0x10a0f
movl 0x38(%rbx), %eax
cmpq $0x3, %rax
ja 0x10a3e
andb $0x1, %dl
movb %dl, 0x3c(%rbx,%rax)
incl %eax
movl %eax, 0x38(%rbx)
jmp 0x10b5b
andl $0x0, 0x38(%rbx)
addl $0xffff8000, %ecx       # imm = 0xFFFF8000
shrl $0xd, %ecx
cmpl $0x3, %ecx
ja 0x10b5b
leaq 0x3b30(%rip), %rax      # 0x1455c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
orb $0xc, 0x28(%rbx)
jmp 0x10b5b
cmpl $0x4, %eax
jne 0x10b5b
andb $0x1, %dl
movb %dl, 0x40(%rbx)
andl $0x0, 0x38(%rbx)
addl $0xffff8000, %ecx       # imm = 0xFFFF8000
shrl $0xd, %ecx
cmpl $0x3, %ecx
ja 0x10b5b
movl %esi, %ebp
leaq 0x3b00(%rip), %rax      # 0x1456c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movzbl 0x28(%rbx), %r14d
movl %r14d, %r15d
andl $0x1, %r15d
leaq 0x3c(%rbx), %rsi
callq 0x10c7e
movl %eax, %edx
andb $0x1f, %dl
movl %r14d, %ecx
andb $-0x20, %cl
orb %dl, %cl
movb %cl, 0x28(%rbx)
andl $0x1, %eax
cmpl %r15d, %eax
je 0x10b0e
movq 0xa507(%rip), %rdi      # 0x1afb0
leaq 0x3ad9(%rip), %rsi      # 0x14589
callq 0x4390
xorl %esi, %esi
testb %r15b, %r15b
sete %sil
movq %rax, %rdi
callq 0x45d0
leaq 0x368d(%rip), %rsi      # 0x1415a
movq %rax, %rdi
callq 0x4390
movq %rax, %rdi
callq 0x41c0
testb $0x1, 0x28(%rbx)
jne 0x10afb
movq (%rbx), %rax
pushq $0x3
popq %rdx
movq %rbx, %rdi
movl %ebp, %esi
xorl %ecx, %ecx
callq *0x50(%rax)
movb 0x28(%rbx), %cl
testb $0x1, %cl
je 0x10b0e
movq (%rbx), %rax
pushq $0x2
popq %rdx
movq %rbx, %rdi
movl %ebp, %esi
xorl %ecx, %ecx
callq *0x50(%rax)
movb 0x28(%rbx), %cl
xorb %r14b, %cl
testb $0x2, %cl
je 0x10b5b
movq 0xa493(%rip), %rdi      # 0x1afb0
leaq 0x3a7d(%rip), %rsi      # 0x145a1
callq 0x4390
movq %rax, %rdi
callq 0x41c0
movb 0x28(%rbx), %cl
testb $0x2, %cl
jne 0x10c62
movq (%rbx), %rax
movq 0x50(%rax), %rax
pushq $0x4
jmp 0x10c74
andb $-0x20, 0x30(%rbx)
jmp 0x10b5b
andb $-0x10, 0x34(%rbx)
jmp 0x10b5b
andb $-0x20, 0x2c(%rbx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3c(%rbx), %rsi
callq 0x10c7e
movb 0x30(%rbx), %cl
andb $0x1f, %al
andb $-0x20, %cl
orb %al, %cl
movb %cl, 0x30(%rbx)
jmp 0x10bce
leaq 0x3c(%rbx), %rsi
callq 0x10c7e
movb 0x28(%rbx), %cl
movb 0x34(%rbx), %dl
movl %eax, %esi
andb $0xf, %sil
andb $-0x10, %dl
orb %sil, %dl
movb %dl, 0x34(%rbx)
testb $0x8, %cl
jne 0x10c31
andl $0xe, %eax
shll $0xe, %eax
movl %eax, 0x44(%rbx)
orl $0x4000, %eax           # imm = 0x4000
jmp 0x10c5a
leaq 0x3c(%rbx), %rsi
callq 0x10c7e
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 0x10bf6
shll $0xd, %ecx
leal 0x1000(%rcx), %r14d
jmp 0x10c06
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
pushq $0x1
popq %rdx
movq %rbx, %rdi
movl %ebp, %esi
movl %r14d, %ecx
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmpq *%rax
testb $0x4, %cl
jne 0x10c42
andl $0x0, 0x44(%rbx)
andl $0xf, %eax
shll $0xe, %eax
jmp 0x10c5a
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 0x10b5b
movq (%rbx), %rax
movq 0x50(%rax), %rax
testb $0x1, %cl
jne 0x10c72
pushq $0x3
jmp 0x10c74
pushq $0x2
popq %rdx
movq %rbx, %rdi
movl %ebp, %esi
xorl %ecx, %ecx
jmp 0x10c25