// File: mindbeast[P]rnes/apu.cpp
// Function: Rnes::Apu::tick()
void Apu::tick() {
  // Divider logic for frame
  if (frameDivider == 0) {
    stepAdvance();
  }
  frameDivider = (frameDivider + 1) % frameCycles;

  // Divider logic for timers
  stepFastTimers();
  if (halfTimerDivider == 0) {
    stepSlowTimers();
  }
  halfTimerDivider = !halfTimerDivider;

  // Compute output each cycle
  sampleOffset += 1;
  float sample =
      95.88f /
      ((8128.0f / (float(pulseA->getCurrentSample() + pulseB->getCurrentSample()))) + 100.0f);
  sample += 159.79f / (100.0f + (1.0f / ((float(triangle->getCurrentSample()) / 8227.0f) +
                                         float(noise->getCurrentSample()) / 12241.0f)));
  samples[sampleOffset % sampleBufferSize] = sample;

  // Determine when to sample, and sample if needed.
  nextSampleCountdown--;
  if (!nextSampleCountdown) {
    float prevSampleClk = currentSampleClk;
    currentSampleClk += clksPerSample;
    nextSampleCountdown = (uint32_t)currentSampleClk - (uint32_t)prevSampleClk;
    if (currentSampleClk >= float(cpuClk)) {
      currentSampleClk = 0.0f;
    }
    generateSample();
  }

  /*
  if (samplerDivider == 0) {
  }
  samplerDivider = (samplerDivider + 1) % uint32_t(cpuClk/ sampleRate);
  */
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x18(%rbp)
cmpl $0x0, 0x10(%rax)
jne 0x26303
movq -0x18(%rbp), %rdi
callq 0x25f20
movq -0x18(%rbp), %rdi
movl 0x10(%rdi), %eax
addl $0x1, %eax
movl $0x1d21, %ecx           # imm = 0x1D21
xorl %edx, %edx
divl %ecx
movl %edx, 0x10(%rdi)
callq 0x26000
movq -0x18(%rbp), %rax
cmpl $0x0, 0x18(%rax)
jne 0x26331
movq -0x18(%rbp), %rdi
callq 0x26030
movq -0x18(%rbp), %rdi
movl 0x18(%rdi), %eax
testl %eax, %eax
sete %al
movzbl %al, %eax
movl %eax, 0x18(%rdi)
movq 0xb0(%rdi), %rax
incq %rax
movq %rax, 0xb0(%rdi)
addq $0xe8, %rdi
callq 0x27370
movq %rax, %rdi
callq 0x2c120
movq -0x18(%rbp), %rdi
movzbl %al, %eax
movl %eax, -0x20(%rbp)
addq $0xf0, %rdi
callq 0x27370
movq %rax, %rdi
callq 0x2c120
movq -0x18(%rbp), %rdi
movb %al, %cl
movl -0x20(%rbp), %eax
movzbl %cl, %ecx
addl %ecx, %eax
cvtsi2ss %eax, %xmm0
movss 0x430bc(%rip), %xmm1    # 0x6945c
divss %xmm0, %xmm1
movss 0x430a4(%rip), %xmm0    # 0x69450
addss %xmm0, %xmm1
movss 0x430a8(%rip), %xmm0    # 0x69460
divss %xmm1, %xmm0
movss %xmm0, -0xc(%rbp)
addq $0xf8, %rdi
callq 0x27390
movq %rax, %rdi
callq 0x27600
movq -0x18(%rbp), %rdi
movzbl %al, %eax
cvtsi2ss %eax, %xmm0
movss 0x4307c(%rip), %xmm1    # 0x69464
divss %xmm1, %xmm0
movss %xmm0, -0x1c(%rbp)
addq $0x100, %rdi            # imm = 0x100
callq 0x273b0
movq %rax, %rdi
callq 0x2c700
movss -0x1c(%rbp), %xmm1
movb %al, %cl
movq -0x18(%rbp), %rax
movzbl %cl, %ecx
cvtsi2ss %ecx, %xmm0
movss 0x43039(%rip), %xmm2    # 0x69458
divss %xmm2, %xmm0
addss %xmm0, %xmm1
movss 0x43025(%rip), %xmm0    # 0x69454
divss %xmm1, %xmm0
movss 0x43015(%rip), %xmm1    # 0x69450
addss %xmm0, %xmm1
movss 0x43005(%rip), %xmm0    # 0x6944c
divss %xmm1, %xmm0
addss -0xc(%rbp), %xmm0
movss %xmm0, -0xc(%rbp)
movss -0xc(%rbp), %xmm0
movq 0xb0(%rax), %rcx
andq $0x1f, %rcx
movss %xmm0, 0x2c(%rax,%rcx,4)
movl 0x28(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x28(%rax)
cmpl $0x0, 0x28(%rax)
jne 0x264d3
movq -0x18(%rbp), %rax
movss 0x24(%rax), %xmm0
movss %xmm0, -0x10(%rbp)
movss 0x20(%rax), %xmm1
movss 0x24(%rax), %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x24(%rax)
cvttss2si 0x24(%rax), %rcx
cvttss2si -0x10(%rbp), %rdx
subl %edx, %ecx
movl %ecx, 0x28(%rax)
movss 0x24(%rax), %xmm0
movss 0x42faf(%rip), %xmm1    # 0x69468
ucomiss %xmm1, %xmm0
jb 0x264ca
movq -0x18(%rbp), %rax
xorps %xmm0, %xmm0
movss %xmm0, 0x24(%rax)
movq -0x18(%rbp), %rdi
callq 0x26090
addq $0x20, %rsp
popq %rbp
retq
nopl (%rax)