// File: MikuAuahDark[P]midi2sif/src/midi2sif.cpp
// Function: midi2sif(_IO_FILE*)
std::vector<SIFBeatmap> midi2sif(FILE* midi_stream)
{
	char temp_buffer[32];

	if(fread(temp_buffer, 1, 4, midi_stream) != 4)
	{
		unexpected_eof:
		throw std::runtime_error("Unexpected EOF");
	}

	if(memcmp(temp_buffer, "MThd", 4))
		throw std::runtime_error("Not MIDI");

	if(fread(temp_buffer, 1, 4, midi_stream) != 4)
		goto unexpected_eof;

	if((STR2DWORD_BE(temp_buffer)) != 6)
		throw std::runtime_error("Header size not 6");

	uint32_t mtrk_count;
	uint32_t ppqn;
	double tempo = 120.0;
	std::map<uint32_t, std::vector<EventInformation> > raw_event_list;

	if(fread(temp_buffer, 1, 6, midi_stream) != 6)
		goto unexpected_eof;

	mtrk_count = STR2WORD_BE(temp_buffer + 2);
	ppqn = STR2WORD_BE(temp_buffer + 4);

	if(ppqn > 32767)
		throw std::runtime_error("MTC is not supported");

	for(uint32_t i = 0; i < mtrk_count; i++)
	{
		if(fread(temp_buffer, 1, 8, midi_stream) != 8)
			goto unexpected_eof;

		size_t mtrk_len = STR2DWORD_BE(temp_buffer + 4);
		uint32_t timing_total = 0;

		if(memcmp(temp_buffer, "MTrk", 4))
		{
			while(mtrk_len > 0)
			{
				size_t res = fread(temp_buffer, 1, std::min(mtrk_len, size_t(32)), midi_stream);

				if(res == 0)
					goto unexpected_eof;

				mtrk_len -= res;
			}

			continue;
		}

		while(mtrk_len > 0)
		{
			uint32_t timing = ReadVarInt(midi_stream, &mtrk_len);
			int32_t event_byte = fgetc(midi_stream);
			int32_t event_type = event_byte >> 4;

			if(event_byte == EOF)
				goto unexpected_eof;

			mtrk_len--;
			timing_total += timing;

			if(event_type == 8)
			{
				int32_t notepos = fgetc(midi_stream);

				if(notepos == EOF || fgetc(midi_stream) == EOF)
					goto unexpected_eof;

				mtrk_len -= 2;

				EventInformation temp(timing_total, false, notepos, event_byte & 0xF);
				InsertEvent(raw_event_list, temp);
			}
			else if(event_type == 9)
			{
				int32_t notepos = fgetc(midi_stream);

				if(notepos == EOF || fgetc(midi_stream) == EOF)
					goto unexpected_eof;
				
				mtrk_len -= 2;

				EventInformation temp(timing_total, true, notepos, event_byte & 0xF);
				InsertEvent(raw_event_list, temp);
			}
			else if(event_byte == 255)
			{
				int32_t meta_id = fgetc(midi_stream);

				if(meta_id == EOF)
					goto unexpected_eof;

				mtrk_len--;

				size_t data_size = ReadVarInt(midi_stream, &mtrk_len);
				char* data = new char[data_size];

				if(fread(data, 1, data_size, midi_stream) != data_size)
				{
					delete[] data;
					goto unexpected_eof;
				}

				mtrk_len -= data_size;

				EventInformation temp(timing_total, meta_id, std::string(data, data_size));
				InsertEvent(raw_event_list, temp);

				delete[] data;
			}
			else if(event_byte == 240 || event_byte == 247)
			{
				int32_t temp;

				do
				{
					temp = fgetc(midi_stream);

					if(temp == EOF)
						goto unexpected_eof;

					mtrk_len--;
				}
				while(temp != 247);
			}
			else if(fread(temp_buffer, 1, 2, midi_stream) != 2)
				goto unexpected_eof;
			else
				mtrk_len -= 2;
		}
	}

	size_t lowest_tick = 0xFFFFFFFFU;
	size_t highest_tick = 0;

	std::vector<EventInformation> event_list;

	for(std::map<uint32_t, std::vector<EventInformation> >::iterator i = raw_event_list.begin(); i != raw_event_list.end(); i++)
	{
		size_t tick = i->first;
		std::vector<EventInformation>& eis = i->second;

		lowest_tick = std::min(tick, lowest_tick);
		highest_tick = std::max(tick, highest_tick);

		while(eis.size() > 0)
		{
			event_list.push_back(eis.back());
			eis.pop_back();
		}
	}

	std::sort(event_list.begin(), event_list.end());

	int32_t top_index = 0;
	int32_t bottom_index = 127;

	for(std::vector<EventInformation>::iterator i = event_list.begin(); i != event_list.end(); i++)
	{
		EventInformation& x = *i;

		if(x.pos != (-1))
		{
			top_index = std::max(top_index, x.pos);
			bottom_index = std::min(bottom_index, x.pos);
		}
	}

	int32_t mid_index = top_index - bottom_index + 1;

	if(mid_index > 9 || mid_index % 2 == 0)
		throw std::runtime_error("Failed to analyze note position. Make sure you only use 9 note keys or odd amount of note keys");

	if(mid_index != 9 && mid_index % 2 == 1)
	{
		mid_index = (top_index + bottom_index) / 2;
		top_index = mid_index + 4;
		bottom_index = mid_index - 4;
	}

	std::vector<SIFBeatmap> sif_beatmap;
	std::map<SIFBeatmap::NotePos, TemporaryLNQueue> longnote_queue;
	double current_timing_sec = 0.0;
	double add_timing_sec = 60.0 / ppqn / tempo;

	for(size_t tick = lowest_tick; tick <= highest_tick; tick++)
	{
		EventInformation ei = *event_list.begin();

		while(tick >= ei.tick)
		{
			event_list.erase(event_list.begin());

			if(ei.meta == 81)
			{
				tempo = 0.0;

				for(std::string::iterator i = ei.data.begin(); i != ei.data.end(); i++)
					tempo = tempo * 256.0 + uint8_t(*i);

				tempo = floor(600000000 / tempo) / 10;
				add_timing_sec = 60.0 / ppqn / tempo;
			}
			else if(ei.pos != (-1))
			{
				SIFBeatmap::NotePos position = SIFBeatmap::NotePos(ei.pos - bottom_index + 1);
				SIFBeatmap::Attribute attri = SIFBeatmap::Attribute(ei.channel >> 2);
				SIFBeatmap::EffectType effect = SIFBeatmap::EffectType((ei.channel & 0x3) + 1);

				if(attri > 0)
				{
					if(ei.note_on)
					{
						if(effect == SIFBeatmap::LONG_NOTE)
						{
							if(longnote_queue.count(position))
							{
								char temp[32];

								sprintf(temp, "another note in pos %d is in queue", int(position));
								throw std::runtime_error(temp);
							}
							else
								longnote_queue[position] = TemporaryLNQueue(current_timing_sec, attri, position);
						}
						else
						{
							SIFBeatmap beatmap = {current_timing_sec, attri, effect, 2.0, position};
							sif_beatmap.push_back(beatmap);
						}
					}
					else if(ei.note_on == false && effect == SIFBeatmap::LONG_NOTE)
					{
						if(longnote_queue.count(position))
						{
							TemporaryLNQueue queue = longnote_queue[position];
							longnote_queue.erase(longnote_queue.find(position));

							SIFBeatmap beatmap = {queue.timing_sec, attri, SIFBeatmap::LONG_NOTE, current_timing_sec - queue.timing_sec, position};
							sif_beatmap.push_back(beatmap);
						}
						else
						{
							char temp[32];

							sprintf(temp, "queue for pos %d is empty", int(position));
							throw std::runtime_error(temp);
						}
					}
				}
			}

			if(event_list.size() > 0)
				ei = *event_list.begin();
			else
				ei.tick = 0xFFFFFFFFU;
		}

		current_timing_sec += add_timing_sec;
	}

	std::sort(sif_beatmap.begin(), sif_beatmap.end());

	return sif_beatmap;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x560, %rsp            # imm = 0x560
movq %rdi, -0x3f8(%rbp)
movq %rdi, %rax
movq %rax, -0x3f0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x30(%rbp), %rdi
movq -0x10(%rbp), %rcx
movl $0x1, %esi
movl $0x4, %edx
callq 0x2320
cmpq $0x4, %rax
je 0x271f
jmp 0x26c3
movl $0x10, %edi
callq 0x2100
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x400(%rbp)
leaq 0xa94f(%rip), %rsi      # 0xd030
callq 0x20a0
jmp 0x26e8
movq -0x400(%rbp), %rdi
movq 0x11902(%rip), %rsi     # 0x13ff8
movq 0x118d3(%rip), %rdx     # 0x13fd0
callq 0x2380
movq -0x400(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
callq 0x21a0
jmp 0x3aa6
leaq -0x30(%rbp), %rax
movl (%rax), %eax
subl $0x6468544d, %eax       # imm = 0x6468544D
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x2791
movl $0x10, %edi
callq 0x2100
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x408(%rbp)
leaq 0xa8f1(%rip), %rsi      # 0xd044
callq 0x20a0
jmp 0x275a
movq -0x408(%rbp), %rdi
movq 0x11890(%rip), %rsi     # 0x13ff8
movq 0x11861(%rip), %rdx     # 0x13fd0
callq 0x2380
movq -0x408(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
callq 0x21a0
jmp 0x3aa6
leaq -0x30(%rbp), %rdi
movq -0x10(%rbp), %rcx
movl $0x1, %esi
movl $0x4, %edx
callq 0x2320
cmpq $0x4, %rax
je 0x27b3
jmp 0x26c3
leaq -0x30(%rbp), %rdi
callq 0x43b0
cmpl $0x6, %eax
je 0x281d
movl $0x10, %edi
callq 0x2100
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x410(%rbp)
leaq 0xa86e(%rip), %rsi      # 0xd04d
callq 0x20a0
jmp 0x27e6
movq -0x410(%rbp), %rdi
movq 0x11804(%rip), %rsi     # 0x13ff8
movq 0x117d5(%rip), %rdx     # 0x13fd0
callq 0x2380
movq -0x410(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
callq 0x21a0
jmp 0x3aa6
movabsq $0x405e000000000000, %rax # imm = 0x405E000000000000
movq %rax, -0x50(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x43f0
movq -0x10(%rbp), %rcx
leaq -0x30(%rbp), %rdi
movl $0x1, %esi
movl $0x6, %edx
callq 0x2320
movq %rax, -0x418(%rbp)
jmp 0x2854
movq -0x418(%rbp), %rax
cmpq $0x6, %rax
je 0x2881
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3a8b
leaq -0x2e(%rbp), %rdi
callq 0x4410
movw %ax, -0x41a(%rbp)
jmp 0x2893
movw -0x41a(%rbp), %ax
movzwl %ax, %eax
movl %eax, -0x40(%rbp)
leaq -0x2c(%rbp), %rdi
callq 0x4410
movw %ax, -0x41c(%rbp)
jmp 0x28b2
movw -0x41c(%rbp), %ax
movzwl %ax, %eax
movl %eax, -0x44(%rbp)
cmpl $0x7fff, -0x44(%rbp)    # imm = 0x7FFF
jbe 0x2929
movl $0x10, %edi
callq 0x2100
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x428(%rbp)
leaq 0xa779(%rip), %rsi      # 0xd05f
callq 0x20a0
jmp 0x28ed
movq -0x428(%rbp), %rdi
movq 0x116fd(%rip), %rsi     # 0x13ff8
movq 0x116ce(%rip), %rdx     # 0x13fd0
callq 0x2380
jmp 0x3aaf
movq -0x428(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
callq 0x21a0
jmp 0x3a8b
movl $0x0, -0x88(%rbp)
movl -0x88(%rbp), %eax
cmpl -0x40(%rbp), %eax
jae 0x2ff8
movq -0x10(%rbp), %rcx
leaq -0x30(%rbp), %rdi
movl $0x1, %esi
movl $0x8, %edx
callq 0x2320
movq %rax, -0x430(%rbp)
jmp 0x2962
movq -0x430(%rbp), %rax
cmpq $0x8, %rax
je 0x297e
movl $0x2, -0x84(%rbp)
jmp 0x3a70
leaq -0x2c(%rbp), %rdi
callq 0x43b0
movl %eax, -0x434(%rbp)
jmp 0x298f
movl -0x434(%rbp), %eax
movl %eax, %eax
movq %rax, -0x90(%rbp)
movl $0x0, -0x94(%rbp)
leaq -0x30(%rbp), %rax
movl (%rax), %eax
subl $0x6b72544d, %eax       # imm = 0x6B72544D
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x2a75
jmp 0x29c4
cmpq $0x0, -0x90(%rbp)
jbe 0x2a70
leaq -0x30(%rbp), %rax
movq %rax, -0x448(%rbp)
movq $0x20, -0xa8(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x4440
movq %rax, -0x440(%rbp)
jmp 0x2a04
movq -0x448(%rbp), %rdi
movq -0x440(%rbp), %rax
movq (%rax), %rdx
movq -0x10(%rbp), %rcx
movl $0x1, %esi
callq 0x2320
movq %rax, -0x450(%rbp)
jmp 0x2a2c
movq -0x450(%rbp), %rax
movq %rax, -0xa0(%rbp)
cmpq $0x0, -0xa0(%rbp)
jne 0x2a53
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0xa0(%rbp), %rcx
movq -0x90(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x90(%rbp)
jmp 0x29c4
jmp 0x2fe4
jmp 0x2a77
cmpq $0x0, -0x90(%rbp)
jbe 0x2fe2
movq -0x10(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x24e0
movl %eax, -0x454(%rbp)
jmp 0x2a9d
movl -0x454(%rbp), %eax
movl %eax, -0xac(%rbp)
movq -0x10(%rbp), %rdi
callq 0x2340
movl %eax, -0x458(%rbp)
jmp 0x2aba
movl -0x458(%rbp), %eax
movl %eax, -0xb0(%rbp)
movl -0xb0(%rbp), %eax
sarl $0x4, %eax
movl %eax, -0xb4(%rbp)
cmpl $-0x1, -0xb0(%rbp)
jne 0x2aed
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0x90(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x90(%rbp)
movl -0xac(%rbp), %eax
addl -0x94(%rbp), %eax
movl %eax, -0x94(%rbp)
cmpl $0x8, -0xb4(%rbp)
jne 0x2be8
movq -0x10(%rbp), %rdi
callq 0x2340
movl %eax, -0x45c(%rbp)
jmp 0x2b2f
movl -0x45c(%rbp), %eax
movl %eax, -0xb8(%rbp)
cmpl $-0x1, -0xb8(%rbp)
je 0x2b60
movq -0x10(%rbp), %rdi
callq 0x2340
movl %eax, -0x460(%rbp)
jmp 0x2b55
movl -0x460(%rbp), %eax
cmpl $-0x1, %eax
jne 0x2b6f
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0x90(%rbp), %rax
addq $-0x2, %rax
movq %rax, -0x90(%rbp)
movl -0x94(%rbp), %esi
movl -0xb8(%rbp), %ecx
movl -0xb0(%rbp), %r8d
andl $0xf, %r8d
leaq -0xf8(%rbp), %rdi
xorl %edx, %edx
callq 0x4480
jmp 0x2ba8
leaq -0x80(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x25b0
jmp 0x2bba
leaq -0xf8(%rbp), %rdi
callq 0x4530
jmp 0x2fdd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x4530
jmp 0x3a8b
cmpl $0x9, -0xb4(%rbp)
jne 0x2cc2
movq -0x10(%rbp), %rdi
callq 0x2340
movl %eax, -0x464(%rbp)
jmp 0x2c06
movl -0x464(%rbp), %eax
movl %eax, -0xfc(%rbp)
cmpl $-0x1, -0xfc(%rbp)
je 0x2c37
movq -0x10(%rbp), %rdi
callq 0x2340
movl %eax, -0x468(%rbp)
jmp 0x2c2c
movl -0x468(%rbp), %eax
cmpl $-0x1, %eax
jne 0x2c46
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0x90(%rbp), %rax
addq $-0x2, %rax
movq %rax, -0x90(%rbp)
movl -0x94(%rbp), %esi
movl -0xfc(%rbp), %ecx
movl -0xb0(%rbp), %r8d
andl $0xf, %r8d
leaq -0x140(%rbp), %rdi
movl $0x1, %edx
callq 0x4480
jmp 0x2c82
leaq -0x80(%rbp), %rdi
leaq -0x140(%rbp), %rsi
callq 0x25b0
jmp 0x2c94
leaq -0x140(%rbp), %rdi
callq 0x4530
jmp 0x2fdb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x4530
jmp 0x3a8b
cmpl $0xff, -0xb0(%rbp)
jne 0x2f18
movq -0x10(%rbp), %rdi
callq 0x2340
movl %eax, -0x46c(%rbp)
jmp 0x2ce3
movl -0x46c(%rbp), %eax
movl %eax, -0x144(%rbp)
cmpl $-0x1, -0x144(%rbp)
jne 0x2d07
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0x90(%rbp), %rax
decq %rax
movq %rax, -0x90(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x24e0
movl %eax, -0x470(%rbp)
jmp 0x2d30
movl -0x470(%rbp), %eax
movl %eax, %eax
movq %rax, -0x150(%rbp)
movq -0x150(%rbp), %rdi
callq 0x2030
movq %rax, -0x478(%rbp)
jmp 0x2d54
movq -0x478(%rbp), %rax
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rdi
movq -0x150(%rbp), %rdx
movq -0x10(%rbp), %rcx
movl $0x1, %esi
callq 0x2320
movq %rax, -0x480(%rbp)
jmp 0x2d87
movq -0x480(%rbp), %rax
cmpq -0x150(%rbp), %rax
je 0x2dc6
movq -0x158(%rbp), %rax
movq %rax, -0x488(%rbp)
cmpq $0x0, %rax
je 0x2db7
movq -0x488(%rbp), %rdi
callq 0x22e0
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0x150(%rbp), %rcx
movq -0x90(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x90(%rbp)
movl -0x94(%rbp), %eax
movl %eax, -0x4a8(%rbp)
movl -0x144(%rbp), %eax
movl %eax, -0x4a4(%rbp)
movq -0x158(%rbp), %rax
movq %rax, -0x4a0(%rbp)
movq -0x150(%rbp), %rax
movq %rax, -0x498(%rbp)
leaq -0x1b9(%rbp), %rdi
movq %rdi, -0x490(%rbp)
callq 0x23a0
movq -0x4a0(%rbp), %rsi
movq -0x498(%rbp), %rdx
movq -0x490(%rbp), %rcx
leaq -0x1b8(%rbp), %rdi
callq 0x2290
jmp 0x2e48
movl -0x4a4(%rbp), %edx
movl -0x4a8(%rbp), %esi
leaq -0x198(%rbp), %rdi
leaq -0x1b8(%rbp), %rcx
callq 0x4550
jmp 0x2e69
leaq -0x1b8(%rbp), %rdi
callq 0x2160
leaq -0x1b9(%rbp), %rdi
callq 0x2260
leaq -0x80(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0x25b0
jmp 0x2e93
movq -0x158(%rbp), %rax
movq %rax, -0x4b0(%rbp)
cmpq $0x0, %rax
je 0x2eb3
movq -0x4b0(%rbp), %rdi
callq 0x22e0
leaq -0x198(%rbp), %rdi
callq 0x4530
jmp 0x2fd9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x2eea
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x1b8(%rbp), %rdi
callq 0x2160
leaq -0x1b9(%rbp), %rdi
callq 0x2260
jmp 0x3a8b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x4530
jmp 0x3a8b
cmpl $0xf0, -0xb0(%rbp)
je 0x2f30
cmpl $0xf7, -0xb0(%rbp)
jne 0x2f87
jmp 0x2f32
movq -0x10(%rbp), %rdi
callq 0x2340
movl %eax, -0x4b4(%rbp)
jmp 0x2f43
movl -0x4b4(%rbp), %eax
movl %eax, -0x1c0(%rbp)
cmpl $-0x1, -0x1c0(%rbp)
jne 0x2f67
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0x90(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x90(%rbp)
cmpl $0xf7, -0x1c0(%rbp)
jne 0x2f32
jmp 0x2fd7
movq -0x10(%rbp), %rcx
leaq -0x30(%rbp), %rdi
movl $0x1, %esi
movl $0x2, %edx
callq 0x2320
movq %rax, -0x4c0(%rbp)
jmp 0x2fa7
movq -0x4c0(%rbp), %rax
cmpq $0x2, %rax
je 0x2fc3
movl $0x2, -0x84(%rbp)
jmp 0x3a70
movq -0x90(%rbp), %rax
subq $0x2, %rax
movq %rax, -0x90(%rbp)
jmp 0x2fd7
jmp 0x2fd9
jmp 0x2fdb
jmp 0x2fdd
jmp 0x2a77
jmp 0x2fe4
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x2933
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, -0x1c8(%rbp)
movq $0x0, -0x1d0(%rbp)
leaq -0x1e8(%rbp), %rdi
callq 0x40e0
leaq -0x80(%rbp), %rdi
callq 0x45e0
movq %rax, -0x1f0(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x4640
movq %rax, -0x1f8(%rbp)
leaq -0x1f0(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x4610
testb $0x1, %al
jne 0x3057
jmp 0x314e
leaq -0x1f0(%rbp), %rdi
movq %rdi, -0x4d0(%rbp)
callq 0x4670
movq -0x4d0(%rbp), %rdi
movl (%rax), %eax
movq %rax, -0x200(%rbp)
callq 0x4670
addq $0x8, %rax
movq %rax, -0x208(%rbp)
leaq -0x200(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0x4440
movq %rax, -0x4c8(%rbp)
jmp 0x30a6
movq -0x4c8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x1c8(%rbp)
leaq -0x200(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
callq 0x4690
movq %rax, -0x4d8(%rbp)
jmp 0x30d3
movq -0x4d8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x1d0(%rbp)
movq -0x208(%rbp), %rdi
callq 0x4050
cmpq $0x0, %rax
jbe 0x3132
movq -0x208(%rbp), %rdi
callq 0x46d0
movq %rax, %rsi
leaq -0x1e8(%rbp), %rdi
callq 0x4070
jmp 0x3113
movq -0x208(%rbp), %rdi
callq 0x4710
jmp 0x30e4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3a62
jmp 0x3134
leaq -0x1f0(%rbp), %rdi
xorl %esi, %esi
callq 0x4740
movq %rax, -0x210(%rbp)
jmp 0x302b
leaq -0x1e8(%rbp), %rdi
movq %rdi, -0x4e0(%rbp)
callq 0x47c0
movq -0x4e0(%rbp), %rdi
movq %rax, -0x218(%rbp)
callq 0x47f0
movq %rax, -0x220(%rbp)
movq -0x218(%rbp), %rdi
movq -0x220(%rbp), %rsi
callq 0x4780
jmp 0x3190
movl $0x0, -0x224(%rbp)
movl $0x7f, -0x228(%rbp)
leaq -0x1e8(%rbp), %rdi
callq 0x47c0
movq %rax, -0x230(%rbp)
leaq -0x1e8(%rbp), %rdi
callq 0x47f0
movq %rax, -0x238(%rbp)
leaq -0x230(%rbp), %rdi
leaq -0x238(%rbp), %rsi
callq 0x4820
testb $0x1, %al
jne 0x31e6
jmp 0x3280
leaq -0x230(%rbp), %rdi
callq 0x4860
movq %rax, -0x240(%rbp)
movq -0x240(%rbp), %rax
cmpl $-0x1, 0x30(%rax)
je 0x3264
movq -0x240(%rbp), %rsi
addq $0x30, %rsi
leaq -0x224(%rbp), %rdi
callq 0x4880
movq %rax, -0x4e8(%rbp)
jmp 0x3226
movq -0x4e8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x224(%rbp)
movq -0x240(%rbp), %rsi
addq $0x30, %rsi
leaq -0x228(%rbp), %rdi
callq 0x48c0
movq %rax, -0x4f0(%rbp)
jmp 0x3255
movq -0x4f0(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x228(%rbp)
jmp 0x3266
leaq -0x230(%rbp), %rdi
xorl %esi, %esi
callq 0x4900
movq %rax, -0x248(%rbp)
jmp 0x31b7
movl -0x224(%rbp), %eax
subl -0x228(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24c(%rbp)
cmpl $0x9, -0x24c(%rbp)
jg 0x32b1
movl -0x24c(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x3312
movl $0x10, %edi
callq 0x2100
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x4f8(%rbp)
leaq 0x9daa(%rip), %rsi      # 0xd079
callq 0x20a0
jmp 0x32d6
movq -0x4f8(%rbp), %rdi
movq 0x10d14(%rip), %rsi     # 0x13ff8
movq 0x10ce5(%rip), %rdx     # 0x13fd0
callq 0x2380
jmp 0x3aaf
movq -0x4f8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
callq 0x21a0
jmp 0x3a62
cmpl $0x9, -0x24c(%rbp)
je 0x3366
movl -0x24c(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x1, %edx
jne 0x3366
movl -0x224(%rbp), %eax
addl -0x228(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x24c(%rbp)
movl -0x24c(%rbp), %eax
addl $0x4, %eax
movl %eax, -0x224(%rbp)
movl -0x24c(%rbp), %eax
subl $0x4, %eax
movl %eax, -0x228(%rbp)
movq -0x3f8(%rbp), %rdi
movb $0x0, -0x24d(%rbp)
callq 0x4940
leaq -0x280(%rbp), %rdi
callq 0x4960
movq $0x0, -0x288(%rbp)
movl -0x44(%rbp), %eax
cvtsi2sd %rax, %xmm1
movsd 0x9c68(%rip), %xmm0     # 0xd008
divsd %xmm1, %xmm0
divsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x290(%rbp)
movq -0x1c8(%rbp), %rax
movq %rax, -0x298(%rbp)
movq -0x298(%rbp), %rax
cmpq -0x1d0(%rbp), %rax
ja 0x39cb
leaq -0x1e8(%rbp), %rdi
callq 0x47c0
movq %rax, -0x2e0(%rbp)
leaq -0x2e0(%rbp), %rdi
callq 0x4860
movq %rax, %rsi
leaq -0x2d8(%rbp), %rdi
callq 0x4980
jmp 0x3403
jmp 0x3405
movq -0x298(%rbp), %rax
movl -0x2d8(%rbp), %ecx
cmpq %rcx, %rax
jb 0x3982
leaq -0x1e8(%rbp), %rdi
movq %rdi, -0x508(%rbp)
callq 0x47c0
movq %rax, -0x2f0(%rbp)
leaq -0x2e8(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
callq 0x4a50
movq -0x508(%rbp), %rdi
movq -0x2e8(%rbp), %rsi
callq 0x49e0
movq %rax, -0x500(%rbp)
jmp 0x3464
movq -0x500(%rbp), %rax
movq %rax, -0x2f8(%rbp)
cmpl $0x51, -0x2d0(%rbp)
jne 0x3594
xorps %xmm0, %xmm0
movsd %xmm0, -0x50(%rbp)
leaq -0x2d8(%rbp), %rdi
addq $0x10, %rdi
callq 0x21f0
movq %rax, -0x300(%rbp)
leaq -0x2d8(%rbp), %rdi
addq $0x10, %rdi
callq 0x2130
movq %rax, -0x308(%rbp)
leaq -0x300(%rbp), %rdi
leaq -0x308(%rbp), %rsi
callq 0x4a90
testb $0x1, %al
jne 0x34ce
jmp 0x3547
movsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x510(%rbp)
leaq -0x300(%rbp), %rdi
callq 0x4ad0
movsd -0x510(%rbp), %xmm0
movzbl (%rax), %eax
cvtsi2sd %eax, %xmm1
movsd 0x9b22(%rip), %xmm2     # 0xd020
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x50(%rbp)
leaq -0x300(%rbp), %rdi
xorl %esi, %esi
callq 0x4af0
movq %rax, -0x310(%rbp)
jmp 0x349e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3a2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x39bd
movsd -0x50(%rbp), %xmm1
movsd 0x9abc(%rip), %xmm0     # 0xd010
divsd %xmm1, %xmm0
callq 0x2370
movsd 0x9ab3(%rip), %xmm1     # 0xd018
divsd %xmm1, %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x44(%rbp), %eax
cvtsi2sd %rax, %xmm1
movsd 0x9a8a(%rip), %xmm0     # 0xd008
divsd %xmm1, %xmm0
divsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x290(%rbp)
jmp 0x392f
cmpl $-0x1, -0x2a8(%rbp)
je 0x392d
movl -0x2a8(%rbp), %eax
subl -0x228(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x314(%rbp)
movl -0x2a4(%rbp), %eax
sarl $0x2, %eax
movl %eax, -0x318(%rbp)
movl -0x2a4(%rbp), %eax
andl $0x3, %eax
addl $0x1, %eax
movl %eax, -0x31c(%rbp)
cmpl $0x0, -0x318(%rbp)
jle 0x392b
testb $0x1, -0x2a0(%rbp)
je 0x376b
cmpl $0x3, -0x31c(%rbp)
jne 0x370a
leaq -0x280(%rbp), %rdi
leaq -0x314(%rbp), %rsi
callq 0x4b30
movq %rax, -0x518(%rbp)
jmp 0x361a
movq -0x518(%rbp), %rax
cmpq $0x0, %rax
je 0x36ae
movl -0x314(%rbp), %edx
leaq 0x9aa0(%rip), %rsi      # 0xd0d8
xorl %eax, %eax
leaq -0x340(%rbp), %rdi
movq %rdi, -0x528(%rbp)
callq 0x2070
movl $0x10, %edi
callq 0x2100
movq -0x528(%rbp), %rsi
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x520(%rbp)
callq 0x20a0
jmp 0x3672
movq -0x520(%rbp), %rdi
movq 0x10978(%rip), %rsi     # 0x13ff8
movq 0x10949(%rip), %rdx     # 0x13fd0
callq 0x2380
jmp 0x3aaf
movq -0x520(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
callq 0x21a0
jmp 0x39bd
movsd -0x288(%rbp), %xmm0
movl -0x318(%rbp), %esi
movl -0x314(%rbp), %edx
leaq -0x350(%rbp), %rdi
callq 0x4b90
jmp 0x36d0
leaq -0x280(%rbp), %rdi
leaq -0x314(%rbp), %rsi
callq 0x4bc0
movq %rax, -0x530(%rbp)
jmp 0x36ec
movq -0x530(%rbp), %rax
movq -0x350(%rbp), %rcx
movq %rcx, (%rax)
movq -0x348(%rbp), %rcx
movq %rcx, 0x8(%rax)
jmp 0x3766
movq -0x3f8(%rbp), %rdi
movsd -0x288(%rbp), %xmm0
movsd %xmm0, -0x370(%rbp)
movl -0x318(%rbp), %eax
movl %eax, -0x368(%rbp)
movl -0x31c(%rbp), %eax
movl %eax, -0x364(%rbp)
movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000
movq %rax, -0x360(%rbp)
movl -0x314(%rbp), %eax
movl %eax, -0x358(%rbp)
leaq -0x370(%rbp), %rsi
callq 0x4ca0
jmp 0x3764
jmp 0x3766
jmp 0x3929
movb -0x2a0(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x3927
cmpl $0x3, -0x31c(%rbp)
jne 0x3927
leaq -0x280(%rbp), %rdi
leaq -0x314(%rbp), %rsi
callq 0x4b30
movq %rax, -0x538(%rbp)
jmp 0x37a8
movq -0x538(%rbp), %rax
cmpq $0x0, %rax
je 0x38a2
leaq -0x280(%rbp), %rdi
leaq -0x314(%rbp), %rsi
callq 0x4bc0
movq %rax, -0x540(%rbp)
jmp 0x37d5
movq -0x540(%rbp), %rax
movups (%rax), %xmm0
movaps %xmm0, -0x380(%rbp)
leaq -0x280(%rbp), %rdi
leaq -0x314(%rbp), %rsi
callq 0x4d50
movq %rax, -0x548(%rbp)
jmp 0x3802
movq -0x548(%rbp), %rax
movq %rax, -0x388(%rbp)
movq -0x388(%rbp), %rsi
leaq -0x280(%rbp), %rdi
callq 0x4d10
movq %rax, -0x550(%rbp)
jmp 0x382c
movq -0x3f8(%rbp), %rdi
movq -0x550(%rbp), %rax
movq %rax, -0x390(%rbp)
movsd -0x380(%rbp), %xmm0
movsd %xmm0, -0x3b0(%rbp)
movl -0x318(%rbp), %eax
movl %eax, -0x3a8(%rbp)
movl $0x3, -0x3a4(%rbp)
movsd -0x288(%rbp), %xmm0
movsd -0x380(%rbp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x3a0(%rbp)
movl -0x314(%rbp), %eax
movl %eax, -0x398(%rbp)
leaq -0x3b0(%rbp), %rsi
callq 0x4ca0
jmp 0x389d
jmp 0x3925
movl -0x314(%rbp), %edx
leaq 0x984c(%rip), %rsi      # 0xd0fb
xorl %eax, %eax
leaq -0x3d0(%rbp), %rdi
movq %rdi, -0x560(%rbp)
callq 0x2070
movl $0x10, %edi
callq 0x2100
movq -0x560(%rbp), %rsi
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x558(%rbp)
callq 0x20a0
jmp 0x38e9
movq -0x558(%rbp), %rdi
movq 0x10701(%rip), %rsi     # 0x13ff8
movq 0x106d2(%rip), %rdx     # 0x13fd0
callq 0x2380
jmp 0x3aaf
movq -0x558(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
callq 0x21a0
jmp 0x39bd
jmp 0x3927
jmp 0x3929
jmp 0x392b
jmp 0x392d
jmp 0x392f
leaq -0x1e8(%rbp), %rdi
callq 0x4050
cmpq $0x0, %rax
jbe 0x3973
leaq -0x1e8(%rbp), %rdi
callq 0x47c0
movq %rax, -0x3d8(%rbp)
leaq -0x3d8(%rbp), %rdi
callq 0x4860
movq %rax, %rsi
leaq -0x2d8(%rbp), %rdi
callq 0x4d80
jmp 0x3971
jmp 0x397d
movl $0xffffffff, -0x2d8(%rbp) # imm = 0xFFFFFFFF
jmp 0x3405
movsd -0x290(%rbp), %xmm0
addsd -0x288(%rbp), %xmm0
movsd %xmm0, -0x288(%rbp)
leaq -0x2d8(%rbp), %rdi
callq 0x4530
movq -0x298(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x298(%rbp)
jmp 0x33bf
leaq -0x2d8(%rbp), %rdi
callq 0x4530
jmp 0x3a2e
movq -0x3f8(%rbp), %rdi
callq 0x4e20
movq -0x3f8(%rbp), %rdi
movq %rax, -0x3e0(%rbp)
callq 0x4e50
movq %rax, -0x3e8(%rbp)
movq -0x3e0(%rbp), %rdi
movq -0x3e8(%rbp), %rsi
callq 0x4de0
jmp 0x3a06
movb $0x1, -0x24d(%rbp)
movl $0x1, -0x84(%rbp)
leaq -0x280(%rbp), %rdi
callq 0x4e80
testb $0x1, -0x24d(%rbp)
jne 0x3a54
jmp 0x3a48
leaq -0x280(%rbp), %rdi
callq 0x4e80
movq -0x3f8(%rbp), %rdi
callq 0x4ea0
jmp 0x3a62
movq -0x3f8(%rbp), %rdi
callq 0x4ea0
leaq -0x1e8(%rbp), %rdi
callq 0x4350
jmp 0x3a70
leaq -0x1e8(%rbp), %rdi
callq 0x4350
jmp 0x3a8b
leaq -0x80(%rbp), %rdi
callq 0x4f00
movl -0x84(%rbp), %eax
subl $0x1, %eax
je 0x3a96
jmp 0x3a86
jmp 0x26c3
leaq -0x80(%rbp), %rdi
callq 0x4f00
jmp 0x3aa6
movq -0x3f0(%rbp), %rax
addq $0x560, %rsp            # imm = 0x560
popq %rbp
retq
movq -0x38(%rbp), %rdi
callq 0x2390
nop