// File: /workspace/github_cpp_makefile_star2_O2/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, 0x11716(%rip)     # 0x1b83a
je 0xa1c7
movl $0xdfff3, (%rsp)        # imm = 0xDFFF3
movl 0x8151d9(%rip), %eax    # 0x81f310
cmpw $0x0, 0x116f9(%rip)     # 0x1b838
je 0xa14b
cmpw $0x0, 0x116ed(%rip)     # 0x1b836
jne 0xa14f
andl $0x0, (%rsp)
sarl %eax
movzwl 0x815250(%rip), %ecx    # 0x81f3a8
testl %ebx, %ebx
jle 0xa58d
movzwl 0x116cf(%rip), %edx     # 0x1b836
testw %dx, %dx
je 0xa183
addw 0x116c5(%rip), %cx      # 0x1b838
movw %cx, 0x81522e(%rip)     # 0x81f3a8
decl %edx
movw %dx, 0x116b3(%rip)      # 0x1b836
movzwl %cx, %edx
movl 0x815184(%rip), %esi    # 0x81f310
cmpl %edx, %esi
jge 0xa19c
subl %esi, %ecx
movw %cx, 0x81520f(%rip)     # 0x81f3a8
movzwl %cx, %edx
xorl %esi, %esi
cmpl %edx, %eax
setle %sil
movb (%rsp,%rsi,2), %dl
movb 0x815169(%rip), %sil    # 0x81f317
addb %dl, %sil
movb %sil, (%r14)
addb 0x81515d(%rip), %dl     # 0x81f317
movb %dl, 0x1(%r14)
addq $0x2, %r14
addl $-0x2, %ebx
jmp 0xa158
movb 0x8151d3(%rip), %al     # 0x81f3a0
testb %al, %al
je 0xa59f
movzbl 0x11508(%rip), %eax     # 0x1b6e4
xorl %edx, %edx
leaq 0x114f3(%rip), %rsi     # 0x1b6d8
leaq 0x114f4(%rip), %rdi     # 0x1b6e0
leaq 0x81515d(%rip), %r13    # 0x81f350
xorl %ecx, %ecx
xorl %r8d, %r8d
cmpq $0x10, %rdx
je 0xa298
movl %eax, %r9d
shrl %cl, %r9d
andl $0x3, %r9d
cmpl $0x1, %r9d
je 0xa276
testl %r9d, %r9d
jne 0xa25b
movzbl (%rdi), %r9d
movl %r9d, %r10d
andl $-0x10, %r10d
negl %r10d
movswl %r10w, %r11d
shrl $0x3, %r11d
leaq (,%r8,4), %r10
movw %r11w, (%r13,%rdx,2)
movl %r9d, %r11d
shrl $0x3, %r11d
andl $-0x2, %r11d
movw %r11w, 0x2(%r13,%rdx,2)
addl %r9d, %r9d
andl $0x1e, %r9d
movl %r9d, %r11d
negl %r11d
jmp 0xa26a
andl $0x0, (%r13,%rdx,2)
xorl %r11d, %r11d
movq %rdx, %r10
xorl %r9d, %r9d
movw %r11w, 0x4(%r13,%r10,2)
movw %r9w, 0x6(%r13,%r10,2)
cmpw $0x0, (%rsi)
jne 0xa282
andq $0x0, (%r13,%rdx,2)
incq %r8
addl $0x2, %ecx
addq $0x4, %rdx
addq $0x2, %rsi
incq %rdi
jmp 0xa1f8
movl 0x815072(%rip), %ebp    # 0x81f310
sarl %ebp
leaq 0x8150c9(%rip), %r15    # 0x81f370
leaq 0x813cc2(%rip), %r12    # 0x81df70
testl %ebx, %ebx
jle 0xa58d
decb 0x11050(%rip)           # 0x1b30c
jns 0xa2ca
movb $0x31, 0x11047(%rip)    # 0x1b30c
callq 0xa61e
movzwl 0x815069(%rip), %edx    # 0x81f33a
addw 0x11400(%rip), %dx      # 0x1b6d8
movw %dx, 0x81505b(%rip)     # 0x81f33a
movzwl 0x815056(%rip), %ecx    # 0x81f33c
addw 0x113ed(%rip), %cx      # 0x1b6da
movzwl 0x113e8(%rip), %eax     # 0x1b6dc
addw %ax, 0x815043(%rip)     # 0x81f33e
movzwl 0x113dc(%rip), %eax     # 0x1b6de
addw %ax, 0x815037(%rip)     # 0x81f340
movw %cx, 0x81502c(%rip)     # 0x81f33c
movzwl %dx, %esi
movl 0x814ff7(%rip), %eax    # 0x81f310
cmpl %esi, %eax
jge 0xa38b
subl %eax, %edx
movw %dx, 0x815014(%rip)     # 0x81f33a
movb 0x113b8(%rip), %dl      # 0x1b6e4
andb $0x3, %dl
cmpb $0x1, %dl
jne 0xa38b
movq %r15, %rdi
movq %r12, %rsi
callq 0xd5e8
addl $-0xa, %eax
cwtl
movzbl 0x11396(%rip), %ecx     # 0x1b6e0
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814ff2(%rip)     # 0x81f350
movw %dx, 0x814fed(%rip)     # 0x81f352
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814fdd(%rip)     # 0x81f354
movw %cx, 0x814fd8(%rip)     # 0x81f356
movzwl 0x814fb7(%rip), %ecx    # 0x81f33c
movl 0x814f85(%rip), %eax    # 0x81f310
movzwl %cx, %edx
cmpl %edx, %eax
jge 0xa407
subl %eax, %ecx
movw %cx, 0x814fa1(%rip)     # 0x81f33c
movb 0x11343(%rip), %cl      # 0x1b6e4
andb $0xc, %cl
cmpb $0x4, %cl
jne 0xa407
movq %r15, %rdi
movq %r12, %rsi
callq 0xd5e8
addl $-0xa, %eax
cwtl
movzbl 0x11322(%rip), %ecx     # 0x1b6e1
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814f85(%rip)     # 0x81f358
movzwl 0x814f76(%rip), %edx    # 0x81f350
movw %dx, 0x814f79(%rip)     # 0x81f35a
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814f69(%rip)     # 0x81f35c
movzwl 0x814f5a(%rip), %eax    # 0x81f354
movw %ax, 0x814f5d(%rip)     # 0x81f35e
movl 0x814f09(%rip), %eax    # 0x81f310
movzwl 0x814f30(%rip), %ecx    # 0x81f33e
cmpl %ecx, %eax
jge 0xa487
subl %eax, %ecx
movw %cx, 0x814f23(%rip)     # 0x81f33e
movb 0x112c3(%rip), %cl      # 0x1b6e4
andb $0x30, %cl
cmpb $0x10, %cl
jne 0xa487
movq %r15, %rdi
movq %r12, %rsi
callq 0xd5e8
addl $-0xa, %eax
cwtl
movzbl 0x112a3(%rip), %ecx     # 0x1b6e2
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814f0d(%rip)     # 0x81f360
movzwl 0x814ef6(%rip), %edx    # 0x81f350
movw %dx, 0x814f01(%rip)     # 0x81f362
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814ef1(%rip)     # 0x81f364
movzwl 0x814eda(%rip), %eax    # 0x81f354
movw %ax, 0x814ee5(%rip)     # 0x81f366
movl 0x814e89(%rip), %eax    # 0x81f310
movzwl 0x814eb2(%rip), %ecx    # 0x81f340
cmpl %ecx, %eax
jge 0xa506
subl %eax, %ecx
movw %cx, 0x814ea5(%rip)     # 0x81f340
movb 0x11243(%rip), %al      # 0x1b6e4
andb $-0x40, %al
cmpb $0x40, %al
jne 0xa506
movq %r15, %rdi
movq %r12, %rsi
callq 0xd5e8
addl $-0xa, %eax
cwtl
movzbl 0x11226(%rip), %ecx     # 0x1b6e3
movl %ecx, %edx
shrl $0x4, %edx
imull %eax, %edx
incl %edx
shrl $0x2, %edx
movw %dx, 0x814e97(%rip)     # 0x81f368
movzwl 0x814e78(%rip), %edx    # 0x81f350
movw %dx, 0x814e8b(%rip)     # 0x81f36a
andl $0xf, %ecx
imull %eax, %ecx
incl %ecx
shrl $0x2, %ecx
movw %cx, 0x814e7b(%rip)     # 0x81f36c
movzwl 0x814e5c(%rip), %eax    # 0x81f354
movw %ax, 0x814e6f(%rip)     # 0x81f36e
movzwl 0x814e3a(%rip), %ecx    # 0x81f340
movb 0x814e0b(%rip), %dl     # 0x81f317
movzwl 0x814e27(%rip), %esi    # 0x81f33a
xorl %eax, %eax
cmpl %esi, %ebp
setle %al
movzwl 0x814e1b(%rip), %edi    # 0x81f33c
xorl %esi, %esi
cmpl %edi, %ebp
setle %sil
movb 0x8(%r13,%rsi,2), %dil
movzwl 0x814e08(%rip), %r8d    # 0x81f33e
xorl %r9d, %r9d
cmpl %r8d, %ebp
setle %r9b
movzwl %cx, %ecx
xorl %r8d, %r8d
cmpl %ecx, %ebp
setle %r8b
addb (%r13,%rax,2), %dl
addb 0x10(%r13,%r9,2), %dl
addb 0x18(%r13,%r8,2), %dil
subb %dil, %dl
movb %dl, (%r14)
movb 0x814db0(%rip), %cl     # 0x81f317
movb 0xc(%r13,%rsi,2), %dl
addb 0x4(%r13,%rax,2), %cl
addb 0x14(%r13,%r9,2), %cl
addb 0x1c(%r13,%r8,2), %dl
subb %dl, %cl
movb %cl, 0x1(%r14)
addq $0x2, %r14
addl $-0x2, %ebx
jmp 0xa2ae
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x814dfa(%rip), %rdi    # 0x81f3a0
callq 0x65a0
testl %eax, %eax
je 0xa1d5
leaq 0x7216(%rip), %rsi      # 0x117d0
movq %rsp, %r15
movl $0xa8, %edx
movq %r15, %rdi
callq 0x6310
leaq 0x814d9f(%rip), %rdi    # 0x81f370
pushq $0x15
popq %rdx
movq %r15, %rsi
callq 0xee66
leaq 0x2fff(%rip), %rdi      # 0xd5e2
leaq 0x814d86(%rip), %rsi    # 0x81f370
leaq 0x10d0f(%rip), %rdx     # 0x1b300
callq 0x6320
leaq 0x814da3(%rip), %rdi    # 0x81f3a0
callq 0x6270
jmp 0xa1d5
movq %rax, %rbx
leaq 0x814d8f(%rip), %rdi    # 0x81f3a0
callq 0x6250
movq %rbx, %rdi
callq 0x6580