// File: /workspace/github_cpp_makefile_star2_O1/mdpkh[P]retro6k/src/main.cpp
// Function: GenerateStereoAudio(void*, unsigned char*, int)
void GenerateStereoAudio(void* userdata, Uint8* stream, int len) //callback to fill audio buffer
{
	if (!menuhassound)
	{
		static signed char tickcounter{ 49 }; // 900 ticks per 1s at 44.1k sample rate
		static unsigned short phase[4]{ 0, 0, 0, 0 };
		static short lev[16];
		// clipped normal-ish distribution with RMS 8; when multiplied by volume and divided by 4, RMS maxes out at 30 (equal to max vol square wave RMS) while value is clipped at +/-37
		static std::discrete_distribution<short> dis{ 240127971, 49520773, 52161640, 54569628, 56671960, 58394828, 59666729, 60422379, 60606996, 60180662, 53532056, 60180662, 60606996, 60422379, 59666729, 58394828, 56671960, 54569628, 52161640, 49520773, 240127971 };
		for (int v = 0; v < 4; ++v)
		{
			switch ((voicetype)((soundvoicetyperegister >> (v << 1)) & 0x3))
			{
			case voicetype::VT_SQUARE:
				lev[(v << 2)    ] = -(soundvolregister[v] & (short)0xf0) >> 3;
				lev[(v << 2) | 1] = (soundvolregister[v] & (short)0xf0) >> 3;
				lev[(v << 2) | 2] = -(soundvolregister[v] & (short)0xf) << 1;
				lev[(v << 2) | 3] = (soundvolregister[v] & (short)0xf) << 1;
				break;
			case voicetype::VT_NOISE:
				// retain existing levels
				break;
			default:
				// undefined
				lev[(v << 2)    ] = 0;
				lev[(v << 2) | 1] = 0;
				lev[(v << 2) | 2] = 0;
				lev[(v << 2) | 3] = 0;
			}
			if (!soundfreqregister[v])
			{
				lev[v << 2    ] = 0;
				lev[v << 2 | 1] = 0;
				lev[v << 2 | 2] = 0;
				lev[v << 2 | 3] = 0;
			}
		}
		int t = soundspec.freq >> 1;
		for (; len > 0; len -= 2)
		{
			--tickcounter;
			if (tickcounter < 0)
			{
				tickcounter = 49;
				StepSoundSchedules();
			}
			phase[0] += soundfreqregister[0];
			phase[1] += soundfreqregister[1];
			phase[2] += soundfreqregister[2];
			phase[3] += soundfreqregister[3];
			if (phase[0] > soundspec.freq)
			{
				phase[0] -= soundspec.freq;
				if ((voicetype)(soundvoicetyperegister & 0x3) == voicetype::VT_NOISE)
				{ // on falling edge of square wave, sample and hold new random value
					short r = dis(noisegen) - 10;
					lev[0] = (r * ((soundvolregister[0] & (short)0xf0) >> 4) + 1) >> 2;
					lev[1] = lev[0];
					lev[2] = (r * (soundvolregister[0] & (short)0xf) + 1) >> 2;
					lev[3] = lev[2];
				}
			}
			if (phase[1] > soundspec.freq)
			{
				phase[1] -= soundspec.freq;
				if ((voicetype)((soundvoicetyperegister >> 2) & 0x3) == voicetype::VT_NOISE)
				{ // on falling edge of square wave, sample and hold new random value
					short r = dis(noisegen) - 10;
					lev[4] = (r * ((soundvolregister[1] & (short)0xf0) >> 4) + 1) >> 2;
					lev[5] = lev[0];
					lev[6] = (r * (soundvolregister[1] & (short)0xf) + 1) >> 2;
					lev[7] = lev[2];
				}
			}
			if (phase[2] > soundspec.freq)
			{
				phase[2] -= soundspec.freq;
				if ((voicetype)((soundvoicetyperegister >> 4) & 0x3) == voicetype::VT_NOISE)
				{ // on falling edge of square wave, sample and hold new random value
					short r = dis(noisegen) - 10;
					lev[8] = (r * ((soundvolregister[2] & (short)0xf0) >> 4) + 1) >> 2;
					lev[9] = lev[0];
					lev[10] = (r * (soundvolregister[2] & (short)0xf) + 1) >> 2;
					lev[11] = lev[2];
				}
			}
			if (phase[3] > soundspec.freq)
			{
				phase[3] -= soundspec.freq;
				if ((voicetype)((soundvoicetyperegister >> 6) & 0x3) == voicetype::VT_NOISE)
				{ // on falling edge of square wave, sample and hold new random value
					short r = dis(noisegen) - 10;
					lev[12] = (r * ((soundvolregister[3] & (short)0xf0) >> 4) + 1) >> 2;
					lev[13] = lev[0];
					lev[14] = (r * (soundvolregister[3] & (short)0xf) + 1) >> 2;
					lev[15] = lev[2];
				}
			}
			*stream = soundspec.silence
				+ lev[     (int)(phase[0] >= t)]
				- lev[4  | (int)(phase[1] >= t)]
				+ lev[8  | (int)(phase[2] >= t)]
				- lev[12 | (int)(phase[3] >= t)];
			++stream;
			*stream = soundspec.silence
				+ lev[2  | (int)(phase[0] >= t)]
				- lev[6  | (int)(phase[1] >= t)]
				+ lev[10 | (int)(phase[2] >= t)]
				- lev[14 | (int)(phase[3] >= t)];
			++stream;
		}
	}
	else
	{
		static unsigned short phase{ 0 };
		short lev[2]{ -13, 13 };
		int t = soundspec.freq >> 1;
		if (!menubeepfreq || !menubeepdur)
		{
			lev[0] = 0;
			lev[1] = 0;
		}
		for (; len > 0; len -= 2)
		{
			if (menubeepdur)
			{
				phase += menubeepfreq;
				--menubeepdur;
			}
			if (phase > soundspec.freq)
				phase -= soundspec.freq;
			*stream = soundspec.silence + lev[(int)(phase >= t)];
			++stream;
			*stream = soundspec.silence + lev[(int)(phase >= t)];
			++stream;
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movl %edx, %ebx
movq %rsi, %r14
cmpb $0x0, 0x11a15(%rip)     # 0x1c82a
je 0xaec6
movl $0xdfff3, (%rsp)        # imm = 0xDFFF3
cmpw $0x0, 0x119fe(%rip)     # 0x1c828
je 0xae36
cmpw $0x0, 0x119f2(%rip)     # 0x1c826
jne 0xae3d
movl $0x0, (%rsp)
testl %ebx, %ebx
jle 0xb28a
movl 0x8154b5(%rip), %eax    # 0x820300
sarl %eax
movzwl 0x815544(%rip), %ecx    # 0x820398
addl $0x2, %ebx
movzwl 0x119c8(%rip), %edx     # 0x1c826
testw %dx, %dx
je 0xae7a
addw 0x119be(%rip), %cx      # 0x1c828
movw %cx, 0x815527(%rip)     # 0x820398
decl %edx
movw %dx, 0x119ac(%rip)      # 0x1c826
movzwl %cx, %esi
movl 0x81547d(%rip), %edx    # 0x820300
cmpl %esi, %edx
jge 0xae90
subl %edx, %ecx
movw %cx, 0x815508(%rip)     # 0x820398
movzwl %cx, %edx
xorl %esi, %esi
cmpl %edx, %eax
setle %sil
movb (%rsp,%rsi,2), %dl
movb 0x815462(%rip), %sil    # 0x820307
addb %dl, %sil
movb %sil, (%r14)
addb 0x815456(%rip), %dl     # 0x820307
movb %dl, 0x1(%r14)
addq $0x2, %r14
addl $-0x2, %ebx
cmpl $0x2, %ebx
jg 0xae57
jmp 0xb28a
movb 0x8154c4(%rip), %al     # 0x820390
testb %al, %al
je 0xb29c
movzbl 0x117f9(%rip), %eax     # 0x1c6d4
xorl %edx, %edx
leaq 0x117ec(%rip), %rsi     # 0x1c6d0
leaq 0x117dd(%rip), %rdi     # 0x1c6c8
leaq 0x81544e(%rip), %r13    # 0x820340
xorl %ecx, %ecx
xorl %r8d, %r8d
movl %eax, %r9d
shrl %cl, %r9d
andl $0x3, %r9d
cmpl $0x1, %r9d
je 0xaf6e
testl %r9d, %r9d
jne 0xaf4b
movzbl (%rsi), %r9d
movl %r9d, %r10d
andl $-0x10, %r10d
negl %r10d
movswl %r10w, %r10d
shrl $0x3, %r10d
movw %r10w, (%r13,%rdx,2)
movl %r9d, %r10d
shrl $0x3, %r10d
andl $-0x2, %r10d
movw %r10w, 0x2(%r13,%rdx,2)
addl %r9d, %r9d
andl $0x1e, %r9d
movl %r9d, %r10d
negl %r10d
movq %rdx, %r11
jmp 0xaf62
leaq (,%r8,4), %r11
movl $0x0, (%r13,%rdx,2)
xorl %r10d, %r10d
xorl %r9d, %r9d
movw %r10w, 0x4(%r13,%r11,2)
movw %r9w, 0x6(%r13,%r11,2)
cmpw $0x0, (%rdi)
jne 0xaf7d
movq $0x0, (%r13,%rdx,2)
incq %r8
addl $0x2, %ecx
addq $0x4, %rdx
incq %rsi
addq $0x2, %rdi
cmpq $0x10, %rdx
jne 0xaef7
testl %ebx, %ebx
jle 0xb28a
movl 0x81535a(%rip), %ebp    # 0x820300
sarl %ebp
addl $0x2, %ebx
leaq 0x813fae(%rip), %r15    # 0x81ef60
leaq 0x8153a7(%rip), %r12    # 0x820360
decb 0x1133d(%rip)           # 0x1c2fc
jns 0xafcd
movb $0x31, 0x11334(%rip)    # 0x1c2fc
callq 0xb31d
movzwl 0x815356(%rip), %eax    # 0x82032a
addw 0x116ed(%rip), %ax      # 0x1c6c8
movzwl 0x116e8(%rip), %ecx     # 0x1c6ca
addw %cx, 0x815343(%rip)     # 0x82032c
movzwl 0x116dc(%rip), %ecx     # 0x1c6cc
addw %cx, 0x815337(%rip)     # 0x82032e
movzwl 0x116d0(%rip), %ecx     # 0x1c6ce
addw %cx, 0x81532b(%rip)     # 0x820330
movw %ax, 0x81531e(%rip)     # 0x82032a
movzwl %ax, %edx
movl 0x8152eb(%rip), %ecx    # 0x820300
cmpl %edx, %ecx
jge 0xb07b
subl %ecx, %eax
movw %ax, 0x815308(%rip)     # 0x82032a
movb 0x116ac(%rip), %al      # 0x1c6d4
andb $0x3, %al
cmpb $0x1, %al
jne 0xb07b
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x10b16
addl $-0xa, %eax
cwtl
movzbl 0x11689(%rip), %ecx     # 0x1c6d0
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x8152e5(%rip)     # 0x820340
movw %dx, 0x8152e0(%rip)     # 0x820342
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x8152d0(%rip)     # 0x820344
movw %cx, 0x8152cb(%rip)     # 0x820346
movzwl 0x8152aa(%rip), %eax    # 0x82032c
movl 0x815278(%rip), %ecx    # 0x820300
cmpl %eax, %ecx
jge 0xb0fc
subl %ecx, %eax
movw %ax, 0x815297(%rip)     # 0x82032c
movb 0x11639(%rip), %al      # 0x1c6d4
andb $0xc, %al
cmpb $0x4, %al
jne 0xb0fc
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x10b16
addl $-0xa, %eax
cwtl
movzbl 0x11617(%rip), %ecx     # 0x1c6d1
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x81527a(%rip)     # 0x820348
movzwl 0x81526b(%rip), %edx    # 0x820340
movw %dx, 0x81526e(%rip)     # 0x82034a
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x81525e(%rip)     # 0x82034c
movzwl 0x81524f(%rip), %eax    # 0x820344
movw %ax, 0x815252(%rip)     # 0x82034e
movzwl 0x81522b(%rip), %eax    # 0x82032e
movl 0x8151f7(%rip), %ecx    # 0x820300
cmpl %eax, %ecx
jge 0xb17d
subl %ecx, %eax
movw %ax, 0x815218(%rip)     # 0x82032e
movb 0x115b8(%rip), %al      # 0x1c6d4
andb $0x30, %al
cmpb $0x10, %al
jne 0xb17d
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x10b16
addl $-0xa, %eax
cwtl
movzbl 0x11597(%rip), %ecx     # 0x1c6d2
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x815201(%rip)     # 0x820350
movzwl 0x8151ea(%rip), %edx    # 0x820340
movw %dx, 0x8151f5(%rip)     # 0x820352
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x8151e5(%rip)     # 0x820354
movzwl 0x8151ce(%rip), %eax    # 0x820344
movw %ax, 0x8151d9(%rip)     # 0x820356
movzwl 0x8151ac(%rip), %eax    # 0x820330
movl 0x815176(%rip), %ecx    # 0x820300
cmpl %eax, %ecx
jge 0xb1fe
subl %ecx, %eax
movw %ax, 0x815199(%rip)     # 0x820330
movb 0x11537(%rip), %al      # 0x1c6d4
andb $-0x40, %al
cmpb $0x40, %al
jne 0xb1fe
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x10b16
addl $-0xa, %eax
cwtl
movzbl 0x11517(%rip), %ecx     # 0x1c6d3
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x815188(%rip)     # 0x820358
movzwl 0x815169(%rip), %edx    # 0x820340
movw %dx, 0x81517c(%rip)     # 0x82035a
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x81516c(%rip)     # 0x82035c
movzwl 0x81514d(%rip), %eax    # 0x820344
movw %ax, 0x815160(%rip)     # 0x82035e
movb 0x815103(%rip), %dl     # 0x820307
movzwl 0x81511f(%rip), %ecx    # 0x82032a
xorl %eax, %eax
cmpl %ecx, %ebp
setle %al
movzwl 0x815113(%rip), %esi    # 0x82032c
xorl %ecx, %ecx
cmpl %esi, %ebp
setle %cl
movb 0x8(%r13,%rcx,2), %sil
movzwl 0x815102(%rip), %edi    # 0x82032e
xorl %r8d, %r8d
cmpl %edi, %ebp
setle %r8b
movzwl 0x8150f4(%rip), %edi    # 0x820330
xorl %r9d, %r9d
cmpl %edi, %ebp
setle %r9b
addb (%r13,%rax,2), %dl
addb 0x10(%r13,%r8,2), %dl
addb 0x18(%r13,%r9,2), %sil
subb %sil, %dl
movb %dl, (%r14)
movb 0x8150a7(%rip), %dl     # 0x820307
addb 0x4(%r13,%rax,2), %dl
addb 0x14(%r13,%r8,2), %dl
movb 0xc(%r13,%rcx,2), %al
addb 0x1c(%r13,%r9,2), %al
subb %al, %dl
movb %dl, 0x1(%r14)
addq $0x2, %r14
addl $-0x2, %ebx
cmpl $0x2, %ebx
jg 0xafb9
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x8150ed(%rip), %rdi    # 0x820390
callq 0x6570
testl %eax, %eax
je 0xaed4
leaq 0x8499(%rip), %rsi      # 0x13750
movq %rsp, %r15
movl $0xa8, %edx
movq %r15, %rdi
callq 0x62f0
leaq 0x815092(%rip), %rdi    # 0x820360
movl $0x15, %edx
movq %r15, %rsi
callq 0x106e8
leaq 0x3a22(%rip), %rdi      # 0xed04
leaq 0x815077(%rip), %rsi    # 0x820360
leaq 0x11000(%rip), %rdx     # 0x1c2f0
callq 0x6300
leaq 0x815094(%rip), %rdi    # 0x820390
callq 0x6250
jmp 0xaed4
movq %rax, %rbx
leaq 0x815080(%rip), %rdi    # 0x820390
callq 0x6230
movq %rbx, %rdi
callq 0x6550