// File: khedoros[P]khednes/apu.cpp
// Function: apu::get_sample(int)
int apu::get_sample(int voice) {
    if(!enabled[voice] || length[voice] == 0 || wavelength_count_reset[voice] == 0) {
        //cout<<"Returning 0"<<endl;
        //cout<<"Enabled: "<<enabled[voice]<<" wavelength: "<<wavelength_count[voice]<<endl;
        return 0;
    }
    //cout<<"Generating something."<<endl;
    int to_gen = 0;
    float interleave = float(CLK_PER_FRAME * 20) / float(SAMPLE_RATE);
    if(interleave - int(interleave) >= 0.5) to_gen = int(interleave) + 1;
    else to_gen = int(interleave);
    //cout<<"to_gen: "<<to_gen<<endl;
    int accum = 0;
    int vol = 0;
    while(to_gen > 0) {
        //cout<<to_gen<<" left to go!"<<endl;
        int this_one = 0;
        if(wavelength_count[voice] == 0) clock_duty(voice);
        if(wavelength_count[voice] >= to_gen) {
            this_one = to_gen;
        }
        else this_one = wavelength_count[voice];
            
        //cout<<"Doing "<<this_one<<" for this iteration"<<endl;
        switch(voice) {
            case SQ1:
                vol = sq1_duty();
                break;
            case SQ2:
                vol = sq2_duty();
                break;
            case TRI:
                vol = tri_duty();
                break;
            case NOISE:
                vol = noise_duty();
                break;
        }
        //if(vol != 0) cout<<"Vol: "<<vol<<endl;
        to_gen -= this_one;
        wavelength_count[voice] -= this_one;
        accum += (vol * this_one);
        if(wavelength_count[voice] == 0) {
            //clock the channel's duty thingie
            clock_duty(voice);
        }
    }
    //cout<<"Accum: "<<accum<<" returning: "<<accum/41<<endl;
    return accum / 41;
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x28(%rsp)
movl %esi, 0x24(%rsp)
movq 0x28(%rsp), %rax
movq %rax, 0x8(%rsp)
movslq 0x24(%rsp), %rcx
testb $0x1, 0xb4(%rax,%rcx)
je 0x2416e
movq 0x8(%rsp), %rax
movslq 0x24(%rsp), %rcx
cmpl $0x0, 0x174(%rax,%rcx,4)
je 0x2416e
movq 0x8(%rsp), %rax
movslq 0x24(%rsp), %rcx
cmpl $0x0, 0x188(%rax,%rcx,4)
jne 0x2417b
movl $0x0, 0x34(%rsp)
jmp 0x2431a
movl $0x0, 0x20(%rsp)
movss 0x8cd5(%rip), %xmm0     # 0x2ce60
movss %xmm0, 0x1c(%rsp)
movss 0x1c(%rsp), %xmm0
cvttss2si 0x1c(%rsp), %eax
cvtsi2ss %eax, %xmm1
subss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x8ba7(%rip), %xmm1     # 0x2cd58
ucomisd %xmm1, %xmm0
jb 0x241c6
cvttss2si 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0x241d0
cvttss2si 0x1c(%rsp), %eax
movl %eax, 0x20(%rsp)
movl $0x0, 0x18(%rsp)
movl $0x0, 0x14(%rsp)
cmpl $0x0, 0x20(%rsp)
jle 0x2430a
movq 0x8(%rsp), %rax
movl $0x0, 0x10(%rsp)
movslq 0x24(%rsp), %rcx
cmpl $0x0, 0x19c(%rax,%rcx,4)
jne 0x24215
movq 0x8(%rsp), %rdi
movl 0x24(%rsp), %esi
callq 0x24580
movq 0x8(%rsp), %rax
movslq 0x24(%rsp), %rcx
movl 0x19c(%rax,%rcx,4), %eax
cmpl 0x20(%rsp), %eax
jl 0x24236
movl 0x20(%rsp), %eax
movl %eax, 0x10(%rsp)
jmp 0x2424b
movq 0x8(%rsp), %rax
movslq 0x24(%rsp), %rcx
movl 0x19c(%rax,%rcx,4), %eax
movl %eax, 0x10(%rsp)
movl 0x24(%rsp), %eax
movq %rax, (%rsp)
subq $0x3, %rax
ja 0x242ab
movq (%rsp), %rax
leaq 0x8b6c(%rip), %rcx      # 0x2cdd0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x8(%rsp), %rdi
callq 0x246c0
movl %eax, 0x14(%rsp)
jmp 0x242ab
movq 0x8(%rsp), %rdi
callq 0x24750
movl %eax, 0x14(%rsp)
jmp 0x242ab
movq 0x8(%rsp), %rdi
callq 0x247e0
movl %eax, 0x14(%rsp)
jmp 0x242ab
movq 0x8(%rsp), %rdi
callq 0x24810
movl %eax, 0x14(%rsp)
movq 0x8(%rsp), %rax
movl 0x10(%rsp), %edx
movl 0x20(%rsp), %ecx
subl %edx, %ecx
movl %ecx, 0x20(%rsp)
movl 0x10(%rsp), %esi
movslq 0x24(%rsp), %rcx
movl 0x19c(%rax,%rcx,4), %edx
subl %esi, %edx
movl %edx, 0x19c(%rax,%rcx,4)
movl 0x14(%rsp), %ecx
imull 0x10(%rsp), %ecx
addl 0x18(%rsp), %ecx
movl %ecx, 0x18(%rsp)
movslq 0x24(%rsp), %rcx
cmpl $0x0, 0x19c(%rax,%rcx,4)
jne 0x24305
movq 0x8(%rsp), %rdi
movl 0x24(%rsp), %esi
callq 0x24580
jmp 0x241e0
movl 0x18(%rsp), %eax
movl $0x29, %ecx
cltd
idivl %ecx
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
addq $0x38, %rsp
retq
nopw %cs:(%rax,%rax)