// File: /workspace/github_c_makefile_star2_O0/calmopyrin[P]tedplay/Sid.cpp
// Function: SIDsound::doEnvelopeGenerator(unsigned int, SIDsound::SIDVoice&)
inline int SIDsound::doEnvelopeGenerator(unsigned int cycles, SIDVoice &v)
{
	unsigned int count = cycles;

	do {
		unsigned int LFSR = v.envCounter;
		if (LFSR != RateCountPeriod[v.envCounterCompare & 0x0f]) {
			const unsigned int feedback = ((LFSR >> 14) ^ (LFSR >> 13)) & 1;
			LFSR = ((LFSR << 1) | feedback) & 0x7FFF;
			v.envCounter = LFSR;
		} else {
			// LFSR = 0x7fff reset LFSR
			v.envCounter = 0x7fff;

			if (v.egState == EG_ATTACK || ++v.envExpCounter == envGenDRdivisors[v.envCurrLevel & 0xff]) {

				v.envExpCounter = 0;

				switch (v.egState) {

				case EG_ATTACK:
					// According to Bob Yannes, Attack is linear...
					if ( ((++v.envCurrLevel) & 0xFF) == 0xFF) {
						v.egState = EG_DECAY;
						v.envCounterCompare = v.envDecaySub;
					}
					break;

				case EG_DECAY:
					if (v.envCurrLevel != v.envSustainLevel) {
						--v.envCurrLevel &= 0xFF;
						if (!v.envCurrLevel)
							v.egState = EG_FROZEN;
					}
					break;

				case EG_RELEASE:
					v.envCurrLevel = (v.envCurrLevel - 1) & 0xFF;
					if (!v.envCurrLevel)
						v.egState = EG_FROZEN;
					break;

				case EG_FROZEN:
					v.envCurrLevel = 0;
					break;
				}
			}
		}
	} while (--count);

	return v.envCurrLevel & 0xFF; // envelope is 8 bits
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x1c(%rbp)
movq -0x18(%rbp), %rax
movl 0x4c(%rax), %eax
movl %eax, -0x20(%rbp)
movl -0x20(%rbp), %eax
movq -0x18(%rbp), %rcx
movl 0x54(%rcx), %ecx
andl $0xf, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x9f99(%rip), %rcx      # 0x1f430
cmpl (%rcx,%rdx,4), %eax
je 0x154cf
movl -0x20(%rbp), %eax
shrl $0xe, %eax
movl -0x20(%rbp), %ecx
shrl $0xd, %ecx
xorl %ecx, %eax
andl $0x1, %eax
movl %eax, -0x24(%rbp)
movl -0x20(%rbp), %eax
shll %eax
orl -0x24(%rbp), %eax
andl $0x7fff, %eax           # imm = 0x7FFF
movl %eax, -0x20(%rbp)
movl -0x20(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x4c(%rax)
jmp 0x155fc
movq -0x18(%rbp), %rax
movl $0x7fff, 0x4c(%rax)     # imm = 0x7FFF
movq -0x18(%rbp), %rax
cmpl $0x1, 0x8(%rax)
je 0x15515
movq -0x18(%rbp), %rcx
movl 0x50(%rcx), %eax
addl $0x1, %eax
movl %eax, 0x50(%rcx)
movq -0x18(%rbp), %rcx
movl 0x48(%rcx), %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x9f67(%rip), %rcx      # 0x1f470
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x155fa
movq -0x18(%rbp), %rax
movl $0x0, 0x50(%rax)
movq -0x18(%rbp), %rax
movl 0x8(%rax), %eax
movq %rax, -0x30(%rbp)
subq $0x3, %rax
ja 0x155f8
movq -0x30(%rbp), %rax
leaq 0xa060(%rip), %rcx      # 0x1f5a0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rcx
movl 0x48(%rcx), %eax
addl $0x1, %eax
movl %eax, 0x48(%rcx)
andl $0xff, %eax
cmpl $0xff, %eax
jne 0x1557b
movq -0x18(%rbp), %rax
movl $0x2, 0x8(%rax)
movq -0x18(%rbp), %rax
movl 0x3c(%rax), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x54(%rax)
jmp 0x155f8
movq -0x18(%rbp), %rax
movl 0x48(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl 0x40(%rcx), %eax
je 0x155bd
movq -0x18(%rbp), %rax
movl 0x48(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x48(%rax)
movl 0x48(%rax), %ecx
andl $0xff, %ecx
movl %ecx, 0x48(%rax)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x48(%rax)
jne 0x155bb
movq -0x18(%rbp), %rax
movl $0x0, 0x8(%rax)
jmp 0x155bd
jmp 0x155f8
movq -0x18(%rbp), %rax
movl 0x48(%rax), %ecx
subl $0x1, %ecx
andl $0xff, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x48(%rax)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x48(%rax)
jne 0x155eb
movq -0x18(%rbp), %rax
movl $0x0, 0x8(%rax)
jmp 0x155f8
movq -0x18(%rbp), %rax
movl $0x0, 0x48(%rax)
jmp 0x155fa
jmp 0x155fc
jmp 0x155fe
movl -0x1c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x1c(%rbp)
cmpl $0x0, %eax
jne 0x15475
movq -0x18(%rbp), %rax
movl 0x48(%rax), %eax
andl $0xff, %eax
popq %rbp
retq
nop