// File: mdpkh[P]retro6k/src/main.cpp
// Function: main
int main(int argc, char** argv)
{
	if (int rv = InitPaths())
		return rv;
	if (int rv = ReadArgs(argc, argv))
		return rv;
	LoadConfig();
	CollapsePaths();
	if (int rv = InitMainWindow())
		return rv;
	if (int rv = InitMemory())
		return rv;
	if (int rv = InitSound())
		return rv;
	menuhassound = true;
	PickAndInsertCartridge();
	menuhassound = false;
	if (int rv = InitEmulator())
		return rv;
	int resetcounter = 0;
	int scanline = 0;
	bool nextframe = false;
	SDL_TimerID frame_timer_id = SDL_AddTimer(16, SetBool, &nextframe);
	SDL_Surface* mwsurface = SDL_GetWindowSurface(mainwindow);
	while (true)
	{
		sysram[0x02fe] = scanline;
		sysram[0x02ff] = scanline >> 8;
		SDL_Event event;
		while (SDL_PollEvent(&event))
		{
			unsigned char inkey;
			switch (event.type)
			{
			case SDL_KEYDOWN:
				if (inkey = keytrans[(event.key.keysym.sym | (event.key.keysym.sym >> 22)) & 0x1ff])
				{
					keypressregister = inkey;
					if (event.key.keysym.mod & KMOD_SHIFT)
						keypressregister ^= 0x20;
					if (event.key.keysym.mod & KMOD_CTRL)
						keypressregister ^= 0x60;
					if (event.key.keysym.mod & KMOD_ALT)
						keypressregister ^= 0x80;
					break;
				}
				switch (event.key.keysym.sym)
				{
				case SDLK_KP_ENTER:
				case SDLK_KP_0:
					DoMenu(0);
					break;
				case SDLK_KP_1:
					DoMenu(1);
					break;
				case SDLK_KP_2:
					DoMenu(2);
					break;
				case SDLK_KP_3:
					DoMenu(3);
					break;
				case SDLK_KP_4:
					DoMenu(4);
					break;
				case SDLK_KP_5:
					DoMenu(5);
					break;
				case SDLK_KP_6:
					DoMenu(6);
					break;
				case SDLK_KP_7:
					DoMenu(7);
					break;
				case SDLK_KP_8:
					DoMenu(8);
					break;
				case SDLK_KP_9:
					DoMenu(9);
					break;
				}
				break;
			case SDL_QUIT:
				goto cleanup;
			default:
				if (event.type == UE_RESETCPU)
				{
					LogReset();
					reset6502();
					stackbase = GetSP();
					resetcounter = 8955;
					LogStep();
				}
			}
		}
		// 6502 clocked at 4MHz, pixel clock at 34.96MHz)
		if (scanline < 576)
		{
			if (!resetcounter)
			{
				LogScanline(scanline);
				videobusy = true;
				videostate = 0x00 | videomode;
				// run 6502 for 21.967963386728 microseconds (768 pixel ticks, 88 cpu cycles)
				exec6502(88);
				RenderScanline(scanline, framebuffer, mwsurface);
				videobusy = false;
				videostate = 0x02 | videomode;
				// run 6502 for 5.949656750572 microseconds (208 pixel ticks, 24 cpu cycles)
				exec6502(12);
				videostate = 0x03 | videomode;
				exec6502(12);
			}
			else
				--resetcounter;
			++scanline;
		}
		else if (scanline < 597)
		{
			// TODO: issue IRQ if video interrupt condition is met
			if (!resetcounter)
			{
				// run 6502 for 27.9176201373 microseconds (976 pixel ticks, 112 cpu cycles)
				LogScanline(scanline);
				if (scanline == 576)
				{
					videostate = 0x20 | videomode;
					exec6502(32);
					videostate = 0x30 | videomode;
					exec6502(56);
					videostate = 0x32 | videomode;
					exec6502(12);
					videostate = 0x33 | videomode;
					exec6502(12);
				}
				else {
					videostate = 0x30 | videomode;
					exec6502(88);
					videostate = 0x32 | videomode;
					exec6502(12);
					videostate = 0x33 | videomode;
					exec6502(12);
				}
			}
			else
				--resetcounter;
			++scanline;
		}
		else if (nextframe)
		{
			scanline = 0;
			nextframe = false;
			SDL_UpdateWindowSurface(mainwindow);
			//RandomBitFlip();
		}
		else
		{
			SDL_Delay(1);
		}
	}
	SDL_RemoveTimer(frame_timer_id);
cleanup:
	SDL_CloseAudioDevice(sounddev);
	SDL_DestroyWindow(mainwindow);
	SDL_FreeSurface(cellcanvas);
	SDL_Quit();
	delete[] sysram;
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
callq 0xee20
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x124d2
movl -0x14(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x1298d
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
callq 0x11e70
movl %eax, -0x18(%rbp)
cmpl $0x0, -0x18(%rbp)
je 0x124f2
movl -0x18(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x1298d
callq 0xf610
callq 0x7a80
callq 0xe3e0
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
je 0x12515
movl -0x1c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x1298d
callq 0xe840
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
je 0x1252e
movl -0x20(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x1298d
callq 0xf580
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x12547
movl -0x24(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x1298d
movb $0x1, 0x1b3dc(%rip)     # 0x2d92a
callq 0xbb00
movb $0x0, 0x1b3d0(%rip)     # 0x2d92a
callq 0xe0b0
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
je 0x12573
movl -0x28(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x1298d
movl $0x0, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movb $0x0, -0x31(%rbp)
movl $0x10, %edi
leaq -0x151(%rip), %rsi      # 0x12440
leaq -0x31(%rbp), %rdx
callq 0x70e0
movl %eax, -0x38(%rbp)
movq 0x81ee44(%rip), %rdi    # 0x8313e8
callq 0x75a0
movq %rax, -0x40(%rbp)
movl -0x30(%rbp), %eax
movb %al, %cl
movq 0x1afa7(%rip), %rax     # 0x2d560
movb %cl, 0x2fe(%rax)
movl -0x30(%rbp), %eax
sarl $0x8, %eax
movb %al, %cl
movq 0x1af92(%rip), %rax     # 0x2d560
movb %cl, 0x2ff(%rax)
leaq -0x78(%rbp), %rdi
callq 0x72b0
cmpl $0x0, %eax
je 0x12773
movl -0x78(%rbp), %eax
movl %eax, -0x80(%rbp)
subl $0x100, %eax            # imm = 0x100
je 0x1273b
jmp 0x125f9
movl -0x80(%rbp), %eax
subl $0x300, %eax            # imm = 0x300
jne 0x12740
jmp 0x12609
movl -0x64(%rbp), %eax
movl -0x64(%rbp), %ecx
sarl $0x16, %ecx
orl %ecx, %eax
andl $0x1ff, %eax            # imm = 0x1FF
movslq %eax, %rcx
leaq 0x10b8d(%rip), %rax     # 0x231b0
movb (%rax,%rcx), %al
movb %al, -0x79(%rbp)
cmpb $0x0, %al
je 0x12695
movb -0x79(%rbp), %al
movb %al, 0x1b18e(%rip)      # 0x2d7c4
movzwl -0x60(%rbp), %eax
andl $0x3, %eax
cmpl $0x0, %eax
je 0x12652
movzbl 0x1b17b(%rip), %eax     # 0x2d7c4
xorl $0x20, %eax
movb %al, 0x1b172(%rip)      # 0x2d7c4
movzwl -0x60(%rbp), %eax
andl $0xc0, %eax
cmpl $0x0, %eax
je 0x12670
movzbl 0x1b15d(%rip), %eax     # 0x2d7c4
xorl $0x60, %eax
movb %al, 0x1b154(%rip)      # 0x2d7c4
movzwl -0x60(%rbp), %eax
andl $0x300, %eax            # imm = 0x300
cmpl $0x0, %eax
je 0x12690
movzbl 0x1b13f(%rip), %eax     # 0x2d7c4
xorl $0x80, %eax
movb %al, 0x1b134(%rip)      # 0x2d7c4
jmp 0x1276e
movl -0x64(%rbp), %eax
addl $0xbfffffa8, %eax       # imm = 0xBFFFFFA8
movl %eax, %ecx
movq %rcx, -0x88(%rbp)
subl $0xa, %eax
ja 0x12739
movq -0x88(%rbp), %rax
leaq 0xdbe7(%rip), %rcx      # 0x202a4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
xorl %edi, %edi
callq 0xa810
jmp 0x12739
movl $0x1, %edi
callq 0xa810
jmp 0x12739
movl $0x2, %edi
callq 0xa810
jmp 0x12739
movl $0x3, %edi
callq 0xa810
jmp 0x12739
movl $0x4, %edi
callq 0xa810
jmp 0x12739
movl $0x5, %edi
callq 0xa810
jmp 0x12739
movl $0x6, %edi
callq 0xa810
jmp 0x12739
movl $0x7, %edi
callq 0xa810
jmp 0x12739
movl $0x8, %edi
callq 0xa810
jmp 0x12739
movl $0x9, %edi
callq 0xa810
jmp 0x1276e
jmp 0x1293e
movl -0x78(%rbp), %eax
cmpl 0x81ecdb(%rip), %eax    # 0x831424
jne 0x1276c
callq 0xf960
callq 0x1ca10
callq 0xe0a0
movb %al, 0x81b1d8(%rip)     # 0x82d938
movl $0x22fb, -0x2c(%rbp)    # imm = 0x22FB
callq 0xe1a0
jmp 0x1276e
jmp 0x125d4
cmpl $0x240, -0x30(%rbp)     # imm = 0x240
jge 0x12816
cmpl $0x0, -0x2c(%rbp)
jne 0x127ff
movl -0x30(%rbp), %edi
callq 0xf980
movb $0x1, 0x1b02b(%rip)     # 0x2d7c0
movzbl 0x1b027(%rip), %eax     # 0x2d7c3
orl $0x0, %eax
movb %al, 0x1b01d(%rip)      # 0x2d7c2
movl $0x58, %edi
callq 0x1cb60
movl -0x30(%rbp), %edi
movq 0x81ec3f(%rip), %rsi    # 0x8313f8
movq -0x40(%rbp), %rdx
callq 0x12340
movb $0x0, 0x1aff7(%rip)     # 0x2d7c0
movzbl 0x1aff3(%rip), %eax     # 0x2d7c3
orl $0x2, %eax
movb %al, 0x1afe9(%rip)      # 0x2d7c2
movl $0xc, %edi
callq 0x1cb60
movzbl 0x1afd9(%rip), %eax     # 0x2d7c3
orl $0x3, %eax
movb %al, 0x1afcf(%rip)      # 0x2d7c2
movl $0xc, %edi
callq 0x1cb60
jmp 0x12808
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x12939
cmpl $0x255, -0x30(%rbp)     # imm = 0x255
jge 0x1290c
cmpl $0x0, -0x2c(%rbp)
jne 0x128f8
movl -0x30(%rbp), %edi
callq 0xf980
cmpl $0x240, -0x30(%rbp)     # imm = 0x240
jne 0x128a8
movzbl 0x1af7e(%rip), %eax     # 0x2d7c3
orl $0x20, %eax
movb %al, 0x1af74(%rip)      # 0x2d7c2
movl $0x20, %edi
callq 0x1cb60
movzbl 0x1af64(%rip), %eax     # 0x2d7c3
orl $0x30, %eax
movb %al, 0x1af5a(%rip)      # 0x2d7c2
movl $0x38, %edi
callq 0x1cb60
movzbl 0x1af4a(%rip), %eax     # 0x2d7c3
orl $0x32, %eax
movb %al, 0x1af40(%rip)      # 0x2d7c2
movl $0xc, %edi
callq 0x1cb60
movzbl 0x1af30(%rip), %eax     # 0x2d7c3
orl $0x33, %eax
movb %al, 0x1af26(%rip)      # 0x2d7c2
movl $0xc, %edi
callq 0x1cb60
jmp 0x128f6
movzbl 0x1af14(%rip), %eax     # 0x2d7c3
orl $0x30, %eax
movb %al, 0x1af0a(%rip)      # 0x2d7c2
movl $0x58, %edi
callq 0x1cb60
movzbl 0x1aefa(%rip), %eax     # 0x2d7c3
orl $0x32, %eax
movb %al, 0x1aef0(%rip)      # 0x2d7c2
movl $0xc, %edi
callq 0x1cb60
movzbl 0x1aee0(%rip), %eax     # 0x2d7c3
orl $0x33, %eax
movb %al, 0x1aed6(%rip)      # 0x2d7c2
movl $0xc, %edi
callq 0x1cb60
jmp 0x12901
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x12937
testb $0x1, -0x31(%rbp)
je 0x1292b
movl $0x0, -0x30(%rbp)
movb $0x0, -0x31(%rbp)
movq 0x81eac4(%rip), %rdi    # 0x8313e8
callq 0x74f0
jmp 0x12935
movl $0x1, %edi
callq 0x7350
jmp 0x12937
jmp 0x12939
jmp 0x125ad
movl 0x81eadc(%rip), %edi    # 0x831420
callq 0x7190
movq 0x81ea98(%rip), %rdi    # 0x8313e8
callq 0x7030
movq 0x81ea94(%rip), %rdi    # 0x8313f0
callq 0x7400
callq 0x7070
movq 0x1abf3(%rip), %rax     # 0x2d560
movq %rax, -0x90(%rbp)
cmpq $0x0, %rax
je 0x12986
movq -0x90(%rbp), %rdi
callq 0x7590
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax)