// File: /workspace/github_c_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movl 0x4c(%rdx), %eax
movl 0x54(%rdx), %r9d
movl 0x40(%rdx), %ecx
movl %ecx, -0x4(%rsp)
movl 0x8(%rdx), %r13d
movl 0x3c(%rdx), %ecx
movl 0x50(%rdx), %r15d
movl 0x48(%rdx), %ebp
leaq 0x61d1(%rip), %rdi      # 0xf1f0
movl $0x1, %r8d
movl $0x2, %r10d
leaq 0x61fe(%rip), %r11      # 0xf230
movl %ebp, %r12d
movl %r9d, %ebx
andl $0xf, %ebx
cmpl (%rdi,%rbx,4), %eax
jne 0x907f
movl $0x7fff, 0x4c(%rdx)     # imm = 0x7FFF
cmpl $0x1, %r13d
jne 0x90a7
andl $0x0, 0x50(%rdx)
incl %r12d
movl %r12d, 0x48(%rdx)
movl $0x7fff, %eax           # imm = 0x7FFF
xorl %r15d, %r15d
cmpb $-0x1, %r12b
jne 0x90f5
movl $0x2, 0x8(%rdx)
movl %ecx, 0x54(%rdx)
movl %r12d, %ebp
movl %r10d, %r13d
movl %ecx, %r9d
jmp 0x909e
movl %eax, %ebx
shrl $0xe, %ebx
movl %eax, %r14d
shrl $0xd, %r14d
xorl %ebx, %r14d
andl $0x1, %r14d
andl $0x3fff, %eax           # imm = 0x3FFF
leal (%r14,%rax,2), %eax
movl %eax, 0x4c(%rdx)
decl %esi
jne 0x9035
jmp 0x9141
incl %r15d
movl %r15d, 0x50(%rdx)
movzbl %r12b, %eax
movzbl (%rax,%r11), %ebx
movl $0x7fff, %eax           # imm = 0x7FFF
cmpl %ebx, %r15d
jne 0x909e
andl $0x0, 0x50(%rdx)
testl %r13d, %r13d
je 0x910b
xorl %r15d, %r15d
cmpl $0x2, %r13d
je 0x90fd
cmpl $0x3, %r13d
jne 0x909e
decl %r12d
movl %r12d, %ebp
andl $0xff, %ebp
movl %ebp, 0x48(%rdx)
je 0x912d
movl %ebp, %r12d
movl $0x3, %r13d
jmp 0x909e
movl %r12d, %ebp
movl %r8d, %r13d
jmp 0x909e
movl -0x4(%rsp), %ebx
cmpl %ebx, %r12d
jne 0x9111
movl %ebx, %r12d
jmp 0x9125
andl $0x0, 0x48(%rdx)
jmp 0x9131
decl %r12d
movl %r12d, %ebp
andl $0xff, %ebp
movl %ebp, 0x48(%rdx)
je 0x912d
movl %ebp, %r12d
movl %r10d, %r13d
jmp 0x909e
andl $0x0, 0x8(%rdx)
xorl %ebp, %ebp
xorl %r12d, %r12d
xorl %r15d, %r15d
xorl %r13d, %r13d
jmp 0x909e
movzbl %bpl, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq