// File: /workspace/github_c_makefile_star2_O2/leiradel[P]zx48k-libretro/src/ay38910.h
// Function: ay38910_tick
bool ay38910_tick(ay38910_t* ay) {
    ay->tick++;
    if ((ay->tick & 7) == 0) {
        /* tick the tone channels */
        for (int i = 0; i < AY38910_NUM_CHANNELS; i++) {
            ay38910_tone_t* chn = &ay->tone[i];
            if (++chn->counter >= chn->period) {
                chn->counter = 0;
                chn->bit ^= 1;
            }
        }

        /* tick the noise channel */
        if (++ay->noise.counter >= ay->noise.period) {
            ay->noise.counter = 0;
            ay->noise.bit ^= 1;
            if (ay->noise.bit) {
                // random number generator from MAME:
                // https://github.com/mamedev/mame/blob/master/src/devices/sound/ay8910.cpp
                // The Random Number Generator of the 8910 is a 17-bit shift
                // register. The input to the shift register is bit0 XOR bit3
                // (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips.
                ay->noise.rng ^= (((ay->noise.rng & 1) ^ ((ay->noise.rng >> 3) & 1)) << 17);
                ay->noise.rng >>= 1;
            }
        }
    }

    /* tick the envelope generator */
    if ((ay->tick & 15) == 0) {
        if (++ay->env.counter >= ay->env.period) {
            ay->env.counter = 0;
            if (!ay->env.shape_holding) {
                ay->env.shape_counter = (ay->env.shape_counter + 1) & 0x1F;
                if (ay->env.shape_hold && (0x1F == ay->env.shape_counter)) {
                    ay->env.shape_holding = true;
                }
            }
            ay->env.shape_state = _ay38910_shapes[ay->env_shape_cycle][ay->env.shape_counter];
        }
    }

    /* generate new sample? */
    ay->sample_counter -= AY38910_FIXEDPOINT_SCALE;
    if (ay->sample_counter <= 0) {
        ay->sample_counter += ay->sample_period;
        float sm = 0.0f;
        for (int i = 0; i < AY38910_NUM_CHANNELS; i++) {
            const ay38910_tone_t* chn = &ay->tone[i];
            float vol;
            if (0 == (ay->reg[AY38910_REG_AMP_A+i] & (1<<4))) {
                /* fixed amplitude */
                vol = _ay38910_volumes[ay->reg[AY38910_REG_AMP_A+i] & 0x0F];
            }
            else {
                /* envelope control */
                vol = _ay38910_volumes[ay->env.shape_state];
            }
            int vol_enable = (chn->bit|chn->tone_disable) & ((ay->noise.rng&1)|(chn->noise_disable));
            if (vol_enable) {
                sm += vol;
            }
        }
        ay->sample = _ay38910_dcadjust(ay, sm) * ay->mag;
        return true;    /* new sample is ready */
    }
    /* fallthrough: no new sample ready yet */
    return false;
}

// Assembly:
movl 0x20(%rdi), %eax
incl %eax
movl %eax, 0x20(%rdi)
testb $0x7, %al
jne 0x356d
xorl %ecx, %ecx
cmpq $0x30, %rcx
je 0x3531
movzwl 0x3a(%rdi,%rcx), %edx
incl %edx
movw %dx, 0x3a(%rdi,%rcx)
cmpw 0x38(%rdi,%rcx), %dx
jb 0x352b
andw $0x0, 0x3a(%rdi,%rcx)
xorb $0x1, 0x3c(%rdi,%rcx)
addq $0x10, %rcx
jmp 0x3507
movzwl 0x6a(%rdi), %ecx
incl %ecx
movw %cx, 0x6a(%rdi)
cmpw 0x68(%rdi), %cx
jb 0x356d
andw $0x0, 0x6a(%rdi)
movl 0x70(%rdi), %ecx
movl %ecx, %edx
xorl $0x1, %edx
movl %edx, 0x70(%rdi)
cmpl $0x1, %ecx
je 0x356d
movl 0x6c(%rdi), %ecx
movl %ecx, %edx
shrl $0x3, %edx
xorl %ecx, %edx
andl $0x1, %edx
shll $0x11, %edx
xorl %ecx, %edx
shrl %edx
movl %edx, 0x6c(%rdi)
testb $0xf, %al
jne 0x35c3
movzwl 0x76(%rdi), %eax
incl %eax
movw %ax, 0x76(%rdi)
cmpw 0x74(%rdi), %ax
jb 0x35c3
andw $0x0, 0x76(%rdi)
movb 0x7a(%rdi), %al
cmpb $0x0, 0x78(%rdi)
jne 0x35a9
incb %al
andb $0x1f, %al
movb %al, 0x7a(%rdi)
cmpb $0x1f, %al
sete %cl
andb 0x79(%rdi), %cl
cmpb $0x1, %cl
jne 0x35a9
movb $0x1, 0x78(%rdi)
movb $0x1f, %al
movzbl 0x32(%rdi), %ecx
movzbl %al, %eax
shll $0x5, %ecx
leaq 0x103e6(%rip), %rdx     # 0x139a0
addq %rcx, %rdx
movb (%rax,%rdx), %al
movb %al, 0x7b(%rdi)
movl 0x8c(%rdi), %eax
leal -0x10(%rax), %ecx
movl %ecx, 0x8c(%rdi)
cmpl $0x10, %eax
jg 0x3699
pushq %rbp
movq %rsp, %rbp
addl 0x88(%rdi), %ecx
movl %ecx, 0x8c(%rdi)
movl 0x6c(%rdi), %ecx
andl $0x1, %ecx
leaq 0x2d(%rdi), %rdx
xorps %xmm0, %xmm0
xorl %esi, %esi
leaq 0x1018f(%rip), %r8      # 0x13790
cmpq $0x30, %rsi
je 0x3642
movzbl (%rdx), %r9d
testb $0x10, %r9b
jne 0x3617
andl $0xf, %r9d
jmp 0x361c
movzbl 0x7b(%rdi), %r9d
movl 0x40(%rdi,%rsi), %r10d
orl 0x3c(%rdi,%rsi), %r10d
movl 0x44(%rdi,%rsi), %r11d
orl %ecx, %r11d
testl %r10d, %r11d
je 0x3639
addss (%r8,%r9,4), %xmm0
addq $0x10, %rsi
incq %rdx
jmp 0x3601
movl 0x9c(%rdi), %ecx
movss 0x98(%rdi), %xmm1
subss 0xa0(%rdi,%rcx,4), %xmm1
addss %xmm0, %xmm1
movss %xmm1, 0x98(%rdi)
movss %xmm0, 0xa0(%rdi,%rcx,4)
incl %ecx
andl $0x1ff, %ecx            # imm = 0x1FF
movl %ecx, 0x9c(%rdi)
mulss 0xf97c(%rip), %xmm1     # 0x13000
addss %xmm0, %xmm1
mulss 0x90(%rdi), %xmm1
movss %xmm1, 0x94(%rdi)
popq %rbp
cmpl $0x11, %eax
setl %al
retq