// File: /workspace/github_cpp_makefile_star2_O3/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, 0x113bd(%rip)     # 0x1c82a
je 0xb51e
movl $0xdfff3, (%rsp)        # imm = 0xDFFF3
cmpw $0x0, 0x113a6(%rip)     # 0x1c828
je 0xb48e
cmpw $0x0, 0x1139a(%rip)     # 0x1c826
jne 0xb495
movl $0x0, (%rsp)
testl %ebx, %ebx
jle 0xb8f8
movl 0x814e5d(%rip), %eax    # 0x820300
sarl %eax
movzwl 0x814eec(%rip), %ecx    # 0x820398
addl $0x2, %ebx
movzwl 0x11370(%rip), %edx     # 0x1c826
testw %dx, %dx
je 0xb4d2
addw 0x11366(%rip), %cx      # 0x1c828
movw %cx, 0x814ecf(%rip)     # 0x820398
decl %edx
movw %dx, 0x11354(%rip)      # 0x1c826
movzwl %cx, %edx
movl 0x814e25(%rip), %esi    # 0x820300
cmpl %edx, %esi
jge 0xb4eb
subl %esi, %ecx
movw %cx, 0x814eb0(%rip)     # 0x820398
movzwl %cx, %edx
xorl %esi, %esi
cmpl %edx, %eax
setle %sil
movb (%rsp,%rsi,2), %dl
movb 0x814e0a(%rip), %sil    # 0x820307
addb %dl, %sil
movb %sil, (%r14)
addb 0x814dfe(%rip), %dl     # 0x820307
movb %dl, 0x1(%r14)
addq $0x2, %r14
addl $-0x2, %ebx
cmpl $0x2, %ebx
jg 0xb4af
jmp 0xb8f8
movb 0x814e6c(%rip), %al     # 0x820390
testb %al, %al
je 0xb90a
movzbl 0x111a1(%rip), %eax     # 0x1c6d4
xorl %edx, %edx
leaq 0x11194(%rip), %rsi     # 0x1c6d0
leaq 0x11185(%rip), %rdi     # 0x1c6c8
leaq 0x814df6(%rip), %r13    # 0x820340
xorl %ecx, %ecx
xorl %r8d, %r8d
movl %eax, %r9d
shrl %cl, %r9d
andl $0x3, %r9d
cmpl $0x1, %r9d
je 0xb5c6
testl %r9d, %r9d
jne 0xb5a3
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 0xb5ba
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 0xb5d5
movq $0x0, (%r13,%rdx,2)
incq %r8
addl $0x2, %ecx
addq $0x4, %rdx
incq %rsi
addq $0x2, %rdi
cmpq $0x10, %rdx
jne 0xb54f
testl %ebx, %ebx
jle 0xb8f8
movl 0x814d02(%rip), %ebp    # 0x820300
sarl %ebp
addl $0x2, %ebx
leaq 0x813956(%rip), %r15    # 0x81ef60
leaq 0x814d4f(%rip), %r12    # 0x820360
decb 0x10ce5(%rip)           # 0x1c2fc
jns 0xb625
movb $0x31, 0x10cdc(%rip)    # 0x1c2fc
callq 0xb98b
movzwl 0x814cfe(%rip), %edx    # 0x82032a
addw 0x11095(%rip), %dx      # 0x1c6c8
movw %dx, 0x814cf0(%rip)     # 0x82032a
movzwl 0x814ceb(%rip), %ecx    # 0x82032c
addw 0x11082(%rip), %cx      # 0x1c6ca
movzwl 0x1107d(%rip), %eax     # 0x1c6cc
addw %ax, 0x814cd8(%rip)     # 0x82032e
movzwl 0x11071(%rip), %eax     # 0x1c6ce
addw %ax, 0x814ccc(%rip)     # 0x820330
movw %cx, 0x814cc1(%rip)     # 0x82032c
movzwl %dx, %esi
movl 0x814c8c(%rip), %eax    # 0x820300
cmpl %esi, %eax
jge 0xb6e9
subl %eax, %edx
movw %dx, 0x814ca9(%rip)     # 0x82032a
movb 0x1104d(%rip), %dl      # 0x1c6d4
andb $0x3, %dl
cmpb $0x1, %dl
jne 0xb6e9
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x1108c
addl $-0xa, %eax
cwtl
movzbl 0x11028(%rip), %ecx     # 0x1c6d0
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814c84(%rip)     # 0x820340
movw %dx, 0x814c7f(%rip)     # 0x820342
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814c6f(%rip)     # 0x820344
movw %cx, 0x814c6a(%rip)     # 0x820346
movzwl 0x814c49(%rip), %ecx    # 0x82032c
movl 0x814c17(%rip), %eax    # 0x820300
movzwl %cx, %edx
cmpl %edx, %eax
jge 0xb768
subl %eax, %ecx
movw %cx, 0x814c33(%rip)     # 0x82032c
movb 0x10fd5(%rip), %cl      # 0x1c6d4
andb $0xc, %cl
cmpb $0x4, %cl
jne 0xb768
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x1108c
addl $-0xa, %eax
cwtl
movzbl 0x10fb1(%rip), %ecx     # 0x1c6d1
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814c14(%rip)     # 0x820348
movzwl 0x814c05(%rip), %edx    # 0x820340
movw %dx, 0x814c08(%rip)     # 0x82034a
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814bf8(%rip)     # 0x82034c
movzwl 0x814be9(%rip), %eax    # 0x820344
movw %ax, 0x814bec(%rip)     # 0x82034e
movl 0x814b98(%rip), %eax    # 0x820300
movzwl 0x814bbf(%rip), %ecx    # 0x82032e
cmpl %ecx, %eax
jge 0xb7eb
subl %eax, %ecx
movw %cx, 0x814bb2(%rip)     # 0x82032e
movb 0x10f52(%rip), %cl      # 0x1c6d4
andb $0x30, %cl
cmpb $0x10, %cl
jne 0xb7eb
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x1108c
addl $-0xa, %eax
cwtl
movzbl 0x10f2f(%rip), %ecx     # 0x1c6d2
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814b99(%rip)     # 0x820350
movzwl 0x814b82(%rip), %edx    # 0x820340
movw %dx, 0x814b8d(%rip)     # 0x820352
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814b7d(%rip)     # 0x820354
movzwl 0x814b66(%rip), %eax    # 0x820344
movw %ax, 0x814b71(%rip)     # 0x820356
movl 0x814b15(%rip), %eax    # 0x820300
movzwl 0x814b3e(%rip), %ecx    # 0x820330
cmpl %ecx, %eax
jge 0xb86d
subl %eax, %ecx
movw %cx, 0x814b31(%rip)     # 0x820330
movb 0x10ecf(%rip), %al      # 0x1c6d4
andb $-0x40, %al
cmpb $0x40, %al
jne 0xb86d
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x1108c
addl $-0xa, %eax
cwtl
movzbl 0x10eaf(%rip), %ecx     # 0x1c6d3
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814b20(%rip)     # 0x820358
movzwl 0x814b01(%rip), %edx    # 0x820340
movw %dx, 0x814b14(%rip)     # 0x82035a
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814b04(%rip)     # 0x82035c
movzwl 0x814ae5(%rip), %eax    # 0x820344
movw %ax, 0x814af8(%rip)     # 0x82035e
movzwl 0x814ac3(%rip), %ecx    # 0x820330
movb 0x814a93(%rip), %sil    # 0x820307
movzwl 0x814aaf(%rip), %edx    # 0x82032a
xorl %eax, %eax
cmpl %edx, %ebp
setle %al
movzwl 0x814aa3(%rip), %edi    # 0x82032c
xorl %edx, %edx
cmpl %edi, %ebp
setle %dl
movb 0x8(%r13,%rdx,2), %dil
movzwl 0x814a91(%rip), %r8d    # 0x82032e
xorl %r9d, %r9d
cmpl %r8d, %ebp
setle %r9b
movzwl %cx, %ecx
xorl %r8d, %r8d
cmpl %ecx, %ebp
setle %r8b
addb (%r13,%rax,2), %sil
addb 0x10(%r13,%r9,2), %sil
addb 0x18(%r13,%r8,2), %dil
subb %dil, %sil
movb %sil, (%r14)
movb 0x814a39(%rip), %cl     # 0x820307
addb 0x4(%r13,%rax,2), %cl
addb 0x14(%r13,%r9,2), %cl
movb 0xc(%r13,%rdx,2), %al
addb 0x1c(%r13,%r8,2), %al
subb %al, %cl
movb %cl, 0x1(%r14)
addq $0x2, %r14
addl $-0x2, %ebx
cmpl $0x2, %ebx
jg 0xb611
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x814a7f(%rip), %rdi    # 0x820390
callq 0x6570
testl %eax, %eax
je 0xb52c
leaq 0x7f7b(%rip), %rsi      # 0x138a0
movq %rsp, %r15
movl $0xa8, %edx
movq %r15, %rdi
callq 0x62f0
leaq 0x814a24(%rip), %rdi    # 0x820360
movl $0x15, %edx
movq %r15, %rsi
callq 0x10c66
leaq 0x399c(%rip), %rdi      # 0xf2ec
leaq 0x814a09(%rip), %rsi    # 0x820360
leaq 0x10992(%rip), %rdx     # 0x1c2f0
callq 0x6300
leaq 0x814a26(%rip), %rdi    # 0x820390
callq 0x6250
jmp 0xb52c
movq %rax, %rbx
leaq 0x814a12(%rip), %rdi    # 0x820390
callq 0x6230
movq %rbx, %rdi
callq 0x6550