// File: /workspace/github_cpp_makefile_star2_O2/khedoros[P]khednes/apu.cpp
// Function: apu::reg_dequeue()
void apu::reg_dequeue() {
    if(writes.size() > 0) {
        int addr = writes.front().second.first - 0x4000;
        int chan = addr / 4;
        int reg = addr % 4;
        if(addr == 0x10) reg = 0x10;
        if(addr == 0x11) reg = 0x11;
        if(addr == 0x12) reg = 0x12;
        if(addr == 0x13) reg = 0x13;
        if(addr == 0x15) reg = 0x15;
        if(addr == 0x17) reg = 0x17;
        int val = writes.front().second.second;
        if(reg < 4 && addr > 0x10) writes.pop_front();
        switch(reg) {
            case 0:
                if(chan != TRI) {
                    vol_reg a;
                    a.val = val;
                    vol[chan] = a.vol;
                    enable_decay[chan] = !a.disable_decay;
                    loop_decay[chan] = a.loop_decay;
                    decay_count[chan] = a.vol;
                    //cout<<"Chan: "<<chan<<" Enable decay: "<<enable_decay[chan]<<" loop: "<<a.loop_decay<<" rate: "<<a.vol<<endl;
                    decay_vol_lvl[chan] = 15;
                    if(chan != NOISE) {
                        duty_cycle[chan] = a.duty_cycle;
                    }
                }
                else {
                    lin_ctr_reg a;
                    a.val = val;
                    linear_cntr = a.count;
                    enable_linear_cntr = a.length_disable;
                }
                break;
            case 1: {
                sweep_reg a;
                a.val = val;
                sweep_enable[chan] = a.enable;
                sweep_shift[chan] = a.shift;
                sweep_rate[chan] = a.rate;
                sweep_count[chan] = a.rate + 1;
                sweep_dir[chan] = a.dir;
                }
                break;
            case 2:
                if(chan != NOISE) {
                    freq_len_reg a;
                    a.freq = wavelength_count_reset[chan];
                    a.low = val;
                    wavelength_count_reset[chan] = a.freq;
                }
                else {
                    freq_len_reg a;
                    a.low = val;
                    wavelength_count_reset[chan] = noise_freq(a);
                    wavelength_count[chan] = noise_freq(a);
                    duty_cycle[chan] = a.noise_type;
                }
                break;
            case 3: 
                if(chan != NOISE) {
                    freq_len_reg a;
                    a.freq = wavelength_count_reset[chan];
                    a.high = val;
                    wavelength_count_reset[chan] = a.freq;
                    wavelength_count[chan] = a.freq;
                    length[chan] = play_length(a);
                }
                else {
                    freq_len_reg a;
                    a.high = val;
                    length[chan] = play_length(a);
                    if(chan == SQ1 || chan == SQ2 || chan == NOISE)
                        decay_vol_lvl[chan] = 15;
                }
                break;
            case 0x10:
                //cout<<"0x4010: Mode: "<<hex<<((val&0xC0)>>(6))<<" Speed: "<<(val&0x0F)<<endl;
                dmc_loop = ((val&0x40) > 0);
                dmc_gen_irq = ((val >= 0x80) && !dmc_loop);
                dmc_freq = dmc_freq_table[val&0x0f]/8;
                dmc_freq_cnt = dmc_freq;
                //cout<<"0x4010: Loop: "<<dmc_loop<<" gen_irq: "<<dmc_gen_irq<<" freq: "<<dmc_freq<<endl;
                if(dmc_gen_irq) cerr<<"DMC can't generate an IRQ, so this game may not work right."<<endl;
                break;
            case 0x11:
                //cout<<"0x4011: PCM/counter val: "<<hex<<val<<endl;
                dmc_pcm_data = (val&0x7f); //The data's just 7 bits
                break;
            case 0x12:
                //cout<<"0x4012: DMC load address: "<<hex<<(((int(val))<<(6))|0xc000)<<endl;
                dmc_addr = (((int(val))<<(6))|0xc000);
                dmc_addr_reset = dmc_addr;
                dmc_bit = 0;
                dmc_cur_byte = memi->read(dmc_addr);
                break;
            case 0x13:
                //cout<<"0x4013: DMC length val: "<<hex<<((int(val))<<(4))<<endl;
                dmc_length = ((int(val))<<(4));
                if(!dmc_length) enabled[DMC] = false;
                break;
            case 0x15: {
                //cout<<"Set 0x15 to "<<val<<endl;
                status_reg a;
                a.val = val;
                enabled[SQ1] = a.sq1_on;
                enabled[SQ2] = a.sq2_on;
                enabled[TRI] = a.tri_on;
                enabled[NOISE] = a.noise_on;
                enabled[DMC] = a.dmc_on;
                //if(enabled[DMC]) cout<<"0x4015 DMC enabled"<<endl;
                //else           cout<<"0x4015 DMC disabled"<<endl;
                pin1_enabled = a.sq1_on + a.sq2_on;
                pin2_enabled = a.tri_on + a.noise_on + a.dmc_on;
                }
                break;
            case 0x17: {
                frame_counter_reg a;
                a.val = val;
                if(a.counter_mode) {
                    clock_quarter();
                    clock_full();
                    framecounter_reset = 111846;
                }
                else {
                    framecounter_reset = 89490;
                }
                enable_irq = !a.irq_disable;
                //cout<<"0x4017: IRQ enable: "<<enable_irq<<endl;
                counter_mode = a.counter_mode;
                framecounter_pos = 0;
                }
                break;
            default:
                cout<<"Not implemented"<<endl;
                break;
        }
        writes.pop_front();
    }
}

// Assembly:
cmpq $0x0, 0x60(%rdi)
je 0xf4ac
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %r14
leaq 0x50(%rdi), %rbx
movq (%rbx), %rax
movl 0x18(%rax), %r13d
movl 0x1c(%rax), %r15d
leal -0x4000(%r13), %ecx
pushq $0x4
popq %rsi
movl %ecx, %eax
cltd
idivl %esi
movl %eax, %ebp
movl %edx, %r12d
cmpl $0x10, %ecx
cmovel %ecx, %r12d
cmpl $0x11, %ecx
cmovel %ecx, %r12d
cmpl $0x12, %ecx
cmovel %ecx, %r12d
cmpl $0x13, %ecx
cmovel %ecx, %r12d
cmpl $0x15, %ecx
cmovel %ecx, %r12d
cmpl $0x17, %ecx
cmovel %ecx, %r12d
cmpl $0x4011, %r13d          # imm = 0x4011
jl 0xf461
cmpl $0x3, %r12d
jg 0xf461
movq %rbx, %rdi
callq 0xfb6e
cmpl $0x17, %r12d
ja 0xf5a7
movl %r12d, %eax
leaq 0x485b(%rip), %rcx      # 0x13cd0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
andl $-0x4, %r13d
cmpl $0x4008, %r13d          # imm = 0x4008
jne 0xf72f
movl %r15d, %eax
andl $0x7f, %eax
movl %eax, 0x118(%r14)
shrb $0x7, %r15b
movb %r15b, 0x11c(%r14)
jmp 0xf7c9
retq
andl $-0x4, %r13d
cmpl $0x400c, %r13d          # imm = 0x400C
jne 0xf70c
movl %r15d, %eax
andl $0xf, %eax
leaq 0x1e045(%rip), %rcx     # 0x2d510
movzwl (%rcx,%rax,2), %eax
movl %eax, 0x194(%r14)
movl %eax, 0x1a8(%r14)
shrl $0x7, %r15d
andl $0x1, %r15d
movl %r15d, 0x110(%r14)
jmp 0xf7c9
andl $0x7f, %r15d
movl %r15d, 0x220(%r14)
jmp 0xf7c9
movslq %ebp, %rax
movl %r15d, %ecx
shrb $0x7, %cl
movb %cl, 0x11d(%r14,%rax)
movl %r15d, %ecx
andl $0x7, %ecx
movl %ecx, 0x124(%r14,%rax,4)
movl %r15d, %ecx
shrl $0x4, %ecx
andl $0x7, %ecx
movl %ecx, 0x14c(%r14,%rax,4)
incl %ecx
movl %ecx, 0x160(%r14,%rax,4)
shrl $0x3, %r15d
andl $0x1, %r15d
movl %r15d, 0x138(%r14,%rax,4)
jmp 0xf7c9
shll $0x6, %r15d
orl $0xc000, %r15d          # imm = 0xC000
movl %r15d, 0x224(%r14)
movl %r15d, 0x228(%r14)
andl $0x0, 0x23c(%r14)
movq 0x30(%r14), %rdi
movl %r15d, %esi
callq 0x96dc
movl %eax, 0x240(%r14)
jmp 0xf7c9
shll $0x4, %r15d
movl %r15d, 0x238(%r14)
jne 0xf7c9
movb $0x0, 0xb8(%r14)
jmp 0xf7c9
movq 0xba02(%rip), %rdi      # 0x1afb0
leaq 0x4a29(%rip), %rsi      # 0x13fde
jmp 0xf651
andl $-0x4, %r13d
cmpl $0x400c, %r13d          # imm = 0x400C
jne 0xf78d
shll $0x8, %r15d
movzwl %r15w, %edi
callq 0xf9a2
movl %eax, 0x180(%r14)
movl $0xf, 0xfc(%r14)
jmp 0xf7c9
movl %r15d, %eax
andl $0x40, %eax
movl %eax, %ecx
shrl $0x6, %ecx
movb %cl, 0x235(%r14)
cmpl $0x7f, %r15d
setg %cl
testl %eax, %eax
sete %sil
movl %ecx, %eax
andb %sil, %al
movb %al, 0x234(%r14)
andl $0xf, %r15d
movl 0x1e0(%r14,%r15,4), %eax
pushq $0x8
popq %rdi
cltd
idivl %edi
movl %eax, 0x230(%r14)
movl %eax, 0x22c(%r14)
andb %sil, %cl
je 0xf7c9
movq 0xb9a6(%rip), %rdi      # 0x1aff0
leaq 0x4951(%rip), %rsi      # 0x13fa2
callq 0x4390
movq %rax, %rdi
callq 0x41c0
jmp 0xf7c9
movl %r15d, %ebp
shrl $0x7, %ebp
movl $0x15d92, %eax          # imm = 0x15D92
andl $0x1, %ebp
je 0xf680
movq %r14, %rdi
callq 0xef60
movl $0x1b4e6, %eax          # imm = 0x1B4E6
movl %eax, 0x1d4(%r14)
testb $0x40, %r15b
sete 0x1d8(%r14)
movl %ebp, 0x1dc(%r14)
andl $0x0, 0x1d0(%r14)
jmp 0xf7c9
movl %r15d, %eax
andl $0x1, %eax
movb %al, 0xb4(%r14)
movl %r15d, %ecx
shrl %ecx
andl $0x1, %ecx
movb %cl, 0xb5(%r14)
movl %r15d, %edx
shrl $0x2, %edx
andl $0x1, %edx
movb %dl, 0xb6(%r14)
movl %r15d, %esi
shrl $0x3, %esi
andl $0x1, %esi
movb %sil, 0xb7(%r14)
shrl $0x4, %r15d
andl $0x1, %r15d
movb %r15b, 0xb8(%r14)
addl %eax, %ecx
movl %ecx, 0x1c4(%r14)
addl %edx, %esi
addl %r15d, %esi
movl %esi, 0x1c8(%r14)
jmp 0xf7c9
movslq %ebp, %rax
movzbl %r15b, %ecx
movl $0x700, %edx            # imm = 0x700
andl 0x188(%r14,%rax,4), %edx
orl %ecx, %edx
movl %edx, 0x188(%r14,%rax,4)
jmp 0xf7c9
movl %r15d, %ecx
andl $0xf, %ecx
movslq %ebp, %rax
movl %ecx, 0xbc(%r14,%rax,4)
testb $0x10, %r15b
sete 0xe4(%r14,%rax)
movl %r15d, %edx
shrb $0x5, %dl
andb $0x1, %dl
movb %dl, 0xe9(%r14,%rax)
movl %ecx, 0xd0(%r14,%rax,4)
movl $0xf, 0xf0(%r14,%rax,4)
cmpl $0x400c, %r13d          # imm = 0x400C
je 0xf7c9
shrl $0x6, %r15d
andl $0x3, %r15d
movl %r15d, 0x104(%r14,%rax,4)
jmp 0xf7c9
movslq %ebp, %r12
movzbl 0x188(%r14,%r12,4), %eax
shll $0x8, %r15d
orl %eax, %r15d
movl %r15d, %eax
andl $0x7ff, %eax            # imm = 0x7FF
movl %eax, 0x188(%r14,%r12,4)
movl %eax, 0x19c(%r14,%r12,4)
movzwl %r15w, %edi
callq 0xf9a2
movl %eax, 0x174(%r14,%r12,4)
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xfb6e
nop