From 0259cc388e24268951370357687912ee8d078c56 Mon Sep 17 00:00:00 2001 From: "sl1nk3.s" Date: Wed, 27 May 2009 21:24:29 +0000 Subject: [PATCH] Some updates to netplay, now using UDP to transmit pad data, it shouldn't be slow as molasses anymore, but may be unrealiable. Netplay now saves settings to ini, also fixed possible desync. +cookie update : Updated Dolphin's icon to be Win7 ready by making it 32x32, so it now shows fine when alt-tabbing :p git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3290 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DolphinWX/Src/Frame.cpp | 2 +- Source/Core/DolphinWX/Src/NetEvent.cpp | 8 +- Source/Core/DolphinWX/Src/NetFunctions.cpp | 202 +++++- Source/Core/DolphinWX/Src/NetSockets.cpp | 225 ++++-- Source/Core/DolphinWX/Src/NetWindow.cpp | 195 +++-- Source/Core/DolphinWX/Src/NetWindow.h | 40 +- Source/Core/DolphinWX/resources/Dolphin.c | 800 +++++++++++++-------- 7 files changed, 1011 insertions(+), 461 deletions(-) diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index 5e99352055..63d182f4a3 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -325,7 +325,7 @@ CFrame::CFrame(bool showLogWindow, // Give it an icon wxIcon IconTemp; - IconTemp.CopyFromBitmap(wxGetBitmapFromMemory(dolphin_png)); + IconTemp.CopyFromBitmap(wxGetBitmapFromMemory(dolphin_ico32x32)); SetIcon(IconTemp); // Give it a status bar diff --git a/Source/Core/DolphinWX/Src/NetEvent.cpp b/Source/Core/DolphinWX/Src/NetEvent.cpp index 847f21a70a..330544d3a8 100644 --- a/Source/Core/DolphinWX/Src/NetEvent.cpp +++ b/Source/Core/DolphinWX/Src/NetEvent.cpp @@ -127,12 +127,15 @@ void ClientSide::OnClientData(unsigned char data) case 0x50: // Everyone is Ready message received { // Load the game and start synching - Event->SendEvent(CLIENTS_READY, "NULL", 1); + m_netptr->LoadGame(); break; } case 0xA1: // Received pad data from host in versus mode { + if (m_data_received) + wxThread::Sleep(10); + m_socket.Receive((char*)m_netvalues[0], 8, recv_size); m_data_received = true; @@ -265,6 +268,9 @@ void ServerSide::OnServerData(char sock, unsigned char data) } case 0xA1: // Received pad data from a client { + if (m_data_received) + wxThread::Sleep(10); + m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size); m_data_received = true; diff --git a/Source/Core/DolphinWX/Src/NetFunctions.cpp b/Source/Core/DolphinWX/Src/NetFunctions.cpp index 1de0aa77be..df3ab47fd8 100644 --- a/Source/Core/DolphinWX/Src/NetFunctions.cpp +++ b/Source/Core/DolphinWX/Src/NetFunctions.cpp @@ -23,13 +23,11 @@ NetPlay *NetClass_ptr = NULL; void NetPlay::IsGameFound(unsigned char * ptr, std::string m_selected) { m_critical.Enter(); - + m_selectedGame = m_selected; if (m_games.find(m_selected) != std::string::npos) - { *ptr = 0x1F; - } else *ptr = 0x1A; @@ -68,6 +66,7 @@ void NetPlay::OnNetEvent(wxCommandEvent& event) // has been killed and so we tell the GUI thread. AppendText(_("*Connection to Host lost.\n*You have been Disconnected.\n\n")); m_isHosting = 2; + m_numClients--; } break; case HOST_PLAYERLEFT: @@ -84,7 +83,9 @@ void NetPlay::OnNetEvent(wxCommandEvent& event) case CLIENTS_READY: { m_clients_ready = true; - if (m_ready || event.GetInt()) + + // Tell clients everyone is ready... + if (m_ready) LoadGame(); } break; @@ -135,25 +136,38 @@ void NetPlay::LoadGame() // and always sends to the server which then send it back to all the clients // -> P2P model is faster, but is limited to 2 players // -> Server model is slower, but supports up to 4 players - - m_Logging->AppendText(_("** Everyone is ready... Loading Game ! **\n")); - - // Tell clients everyone is ready... + if (m_isHosting == 1) { + long ping[3] = {0}; unsigned char value = 0x50; + // Get ping + m_sock_server->Write(0, 0, 0, ping); + float fping = (ping[0]+ping[1]+ping[2])/(float)m_numClients; + + // Tell client everyone is ready for (int i=0; i < m_numClients ; i++) m_sock_server->Write(i, (const char*)&value, 1); + + // Sleep a bit to start the game at more or less the same time than the peer + wxMilliSleep(fping/2); + + m_Logging->AppendText(wxString::Format(wxT("** Everyone is ready... Loading Game ! **\n" + "** Ping to client(s) is : %f ms\n"), fping)); } + else + m_Logging->AppendText(_("** Everyone is ready... Loading Game ! **\n")); // TODO : Throttle should be on by default, to avoid stuttering //soundStream->GetMixer()->SetThrottle(true); - + int line_p = 0; int line_n = 0; + m_critical.Enter(); std::string tmp = m_games.substr(0, m_games.find(m_selectedGame)); + for (int i=0; i < (int)tmp.size(); i++) if (tmp.c_str()[i] == '\n') line_n++; @@ -162,6 +176,7 @@ void NetPlay::LoadGame() NetClass_ptr = this; m_timer.Start(); m_data_received = false; + m_critical.Leave(); // Find corresponding game path for (int i=0; i < (int)m_paths.size(); i++) @@ -182,6 +197,15 @@ void NetPlay::LoadGame() bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues) { + if (m_numClients < 1) + { + m_Logging->AppendText(_("** WARNING : " + "Ping too high (>2000ms) or connection lost ! \n" + "** WARNING : Stopping Netplay... \n")); + NetClass_ptr = NULL; + return false; + } + // Store current pad status in netValues[] netValues[0] = (u32)((u8)PadStatus.stickY); netValues[0] |= (u32)((u8)PadStatus.stickX << 8); @@ -192,34 +216,37 @@ bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues) netValues[1] |= (u32)((u8)PadStatus.substickY << 16); netValues[1] |= (u32)((u8)PadStatus.substickX << 24); - if (m_frame == 0) - { - // We make sure everyone's pad is enabled - for (int i = 0; i < m_numClients+1; i++) - SerialInterface::ChangeDevice(SI_GC_CONTROLLER, i); - - // Better disable unused ports - for (int i = m_numClients+1; i < 4; i++) - SerialInterface::ChangeDevice(SI_DUMMY, i); - } - - if (m_NetModel == 0 && m_numClients == 1) // Use P2P Model + if (m_NetModel == 0) // Use 2 players Model { if (padnb == 0) { - // TODO : actually show this on the GUI :p // Update the timer and increment total frame number m_frame++; - m_timer.Update(); + + if (m_frame == 1) + { + // We make sure everyone's pad is enabled + for (int i = 0; i < m_numClients+1; i++) + SerialInterface::ChangeDevice(SI_GC_CONTROLLER, i); + + // Better disable unused ports + for (int i = m_numClients+1; i < 4; i++) + SerialInterface::ChangeDevice(SI_DUMMY, i); + } + + if (m_timer.GetTimeDifference() > 1000) + m_timer.Update(); #ifdef NET_DEBUG char sent[64]; sprintf(sent, "Sent Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]); m_Logging->AppendText(wxString::FromAscii(sent)); #endif - unsigned char init_value = 0xA1; unsigned char player = 0; +#ifdef USE_TCP + unsigned char init_value = 0xA1; + if (m_isHosting == 1) { // Send pads values m_sock_server->Write(0, (const char*)&init_value, 1); @@ -231,6 +258,23 @@ bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues) m_sock_client->Write((const char*)netValues, 8); player = 1; } +#else // UDP + u32 padsValues[3]; + + padsValues[0] = m_frame; + padsValues[1] = netValues[0]; + padsValues[2] = netValues[1]; + + if (m_isHosting == 1) { + // Send pads values + m_sock_server->WriteUDP(0, (const char*)padsValues, 12); + } + else { + // Send pads values + m_sock_client->WriteUDP((const char*)padsValues, 12); + player = 1; + } +#endif if (!m_data_received) { @@ -257,9 +301,10 @@ bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues) else { if (m_loopframe > 126) { - m_Logging->AppendText(_("** Ping too high (>2000ms) or connection lost ! \n")); - m_Logging->AppendText(_("** Stopping game... \n")); - BootManager::Stop(); + m_Logging->AppendText(_("** WARNING : " + "Ping too high (>2000ms) or connection lost ! \n" + "** WARNING : Stopping Netplay... \n")); + NetClass_ptr = NULL; } m_loopframe++; @@ -367,7 +412,6 @@ void NetPlay::ChangeSelectedGame(std::string game) m_sock_server->Write(i, (const char*)&value, 1); // 0x35 -> Change game m_sock_server->Write(i, (const char*)&game_size, 4); - //m_sock_server->Write(i, m_selectedGame.c_str(), game_size + 1); m_sock_server->Write(i, game.c_str(), game_size + 1); } @@ -379,20 +423,19 @@ void NetPlay::ChangeSelectedGame(std::string game) void NetPlay::OnQuit(wxCloseEvent& WXUNUSED(event)) { + // Disable netplay NetClass_ptr = NULL; - // We Kill the threads + // Destroy the Window + Destroy(); + + // Then Kill the threads if (m_isHosting == 0) m_sock_client->Delete(); else if (m_isHosting == 1) { m_sock_server->Delete(); - // Stop listening, we're doing it here cause Doing it in the thread - // Cause SFML to crash when built in release build, odd ? :( - m_listensocket.Close(); } - // Destroy the Frame - Destroy(); } void NetPlay::OnDisconnect(wxCommandEvent& WXUNUSED(event)) @@ -403,7 +446,7 @@ void NetPlay::OnDisconnect(wxCommandEvent& WXUNUSED(event)) bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus) { - // TODO : adapt it to more than 2 players +#ifdef USE_TCP if (current) { while (1) @@ -419,6 +462,9 @@ bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus) break; } m_CriticalSection.Leave(); + + if (TestDestroy()) + break; } return true; @@ -427,10 +473,54 @@ bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus) wxCriticalSectionLocker lock(m_CriticalSection); return m_data_received; +#else + size_t recv_size; + + if (current) + { + m_CriticalSection.Enter(); + + if (isVersus) + { + if (m_netvalues[0][1] != 0) + { + netValues[0] = m_netvalues[0][1]; + netValues[1] = m_netvalues[0][2]; + } + else + { + while (true) + { + u32 frame_saved = m_netvalues[0][0]; + bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 5); + + if (m_netvalues[0][0] < frame_saved+1) + continue; + if (m_netvalues[0][0] > frame_saved+1 || !pass) + PanicAlert("Network ERROR !"); + + netValues[0] = m_netvalues[0][1]; + netValues[1] = m_netvalues[0][2]; + break; + } + } + } + + m_netvalues[0][1] = 0; + m_CriticalSection.Leave(); + + return true; + } + else + return RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 1/1000); + +#endif + } bool ServerSide::isNewPadData(u32 *netValues, bool current, char client) { +#ifdef USE_TCP if (current) { while (1) @@ -446,6 +536,9 @@ bool ServerSide::isNewPadData(u32 *netValues, bool current, char client) break; } m_CriticalSection.Leave(); + + if (TestDestroy()) + break; } return true; @@ -454,5 +547,44 @@ bool ServerSide::isNewPadData(u32 *netValues, bool current, char client) wxCriticalSectionLocker lock(m_CriticalSection); return m_data_received; +#else + size_t recv_size; + + if (current) + { + m_CriticalSection.Enter(); + + if (m_netvalues[0][1] != 0) + { + netValues[0] = m_netvalues[client][1]; + netValues[1] = m_netvalues[client][2]; + } + else + { + while (true) + { + u32 frame_saved = m_netvalues[client][0]; + bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 5); + + if (m_netvalues[client][0] < frame_saved+1) + continue; + if (m_netvalues[client][0] > frame_saved+1 || !pass) + PanicAlert("Network ERROR !"); + + netValues[0] = m_netvalues[client][1]; + netValues[1] = m_netvalues[client][2]; + break; + } + } + + m_netvalues[client][1] = 0; + m_CriticalSection.Leave(); + + return true; + } + else + return RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 1/1000); + +#endif } diff --git a/Source/Core/DolphinWX/Src/NetSockets.cpp b/Source/Core/DolphinWX/Src/NetSockets.cpp index 69c0137d84..367e431d14 100644 --- a/Source/Core/DolphinWX/Src/NetSockets.cpp +++ b/Source/Core/DolphinWX/Src/NetSockets.cpp @@ -23,9 +23,9 @@ void NetEvent::AppendText(const wxString text) { - // I have the feeling SendEvent may be a bit better... -#if 0 - SendEvent(ADD_TEXT, std::string(text.mb_str())) + // I have the feeling SendEvent may be a bit safer/better... +#if 1 + SendEvent(ADD_TEXT, std::string(text.mb_str())); #else wxMutexGuiEnter(); m_netptr->AppendText(text); @@ -48,13 +48,14 @@ void NetEvent::SendEvent(int EventType, const std::string text, int integer) // SERVER SIDE THREAD //-------------------------------- -ServerSide::ServerSide(NetPlay* netptr, sf::SocketTCP socket, int netmodel, std::string nick) +ServerSide::ServerSide(NetPlay* netptr, sf::SocketTCP socket, sf::SocketUDP socketUDP, int netmodel, std::string nick) : wxThread() { m_numplayers = 0; m_data_received = false; m_netmodel = netmodel; m_socket = socket; + m_socketUDP = socketUDP; m_netptr = netptr; m_nick = nick; Event = new NetEvent(m_netptr); @@ -71,6 +72,23 @@ char ServerSide::GetSocket(sf::SocketTCP Socket) return 0xE; } +bool ServerSide::RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time) +{ + sf::SelectorUDP Selector; + sf::IPAddress Addr; + Selector.Add(Socket); + + if (Selector.Wait(Time) > 0) + { + Socket.Receive(Data, Max, Recvd, Addr); + return true; + } + else + { + return false; + } +} + void *ServerSide::Entry() { // Add listening socket @@ -99,22 +117,30 @@ void *ServerSide::Entry() if ((m_netmodel == 0 && m_numplayers > 0) || m_numplayers == 3) { Incoming.Send((const char *)&sent, 1); // Tell it the server is full... - Incoming.Close(); // Then close the connection + Incoming.Close(); // Then close the connection + Event->AppendText(_(" Server is Full !\n")); } else { Event->AppendText(_(" Connection accepted\n")); m_client[m_numplayers].socket = Incoming; + m_client[m_numplayers].address = Address; + + if (SyncValues(m_numplayers, Address)) + { + // Add it to the selector + m_selector.Add(Incoming); + Event->SendEvent(HOST_NEWPLAYER); - SyncValues(m_numplayers, Address); + m_numplayers++; + } + else + { + Event->AppendText(_("ERROR : Unable to establish UDP connection !\n")); + Incoming.Close(); + } } - - // Add it to the selector - m_selector.Add(Incoming); - Event->SendEvent(HOST_NEWPLAYER); - - m_numplayers++; } else { @@ -122,9 +148,7 @@ void *ServerSide::Entry() int socket_nb; size_t recv_size; sf::Socket::Status recv_status; - - if ((socket_nb = GetSocket(Socket)) == 0xE) - PanicAlert("ERROR: How did you get there ?! Is that even possible ?!"); + socket_nb = GetSocket(Socket); if ((recv_status = Socket.Receive((char *)&recv, 1, recv_size)) == sf::Socket::Done) { @@ -182,6 +206,9 @@ void *ServerSide::Entry() if(TestDestroy()) { + // Stop listening + m_socket.Close(); + // Delete the Thread and close clients sockets for (char i=0; i < m_numplayers ; i++) m_client[i].socket.Close(); @@ -193,7 +220,7 @@ void *ServerSide::Entry() return NULL; } -void ServerSide::SyncValues(unsigned char socketnb, sf::IPAddress Address) +bool ServerSide::SyncValues(unsigned char socketnb, sf::IPAddress Address) { sf::SocketTCP Socket = m_client[socketnb].socket; @@ -201,7 +228,8 @@ void ServerSide::SyncValues(unsigned char socketnb, sf::IPAddress Address) char *buffer = NULL; unsigned char init_number; u32 buffer_size = (u32)buffer_str.size(); - size_t received; + size_t received; + bool errorUDP = false; // First, Send the number of connected clients & netmodel Socket.Send((const char *)&m_numplayers, 1); @@ -216,6 +244,8 @@ void ServerSide::SyncValues(unsigned char socketnb, sf::IPAddress Address) Socket.Send((const char *)&buffer_size, 4); Socket.Send(m_nick.c_str(), buffer_size + 1); + // Read client's UDP Port + Socket.Receive((char *)&m_client[m_numplayers].port, sizeof(short), received); // Read returned nickname Socket.Receive((char *)&buffer_size, 4, received); @@ -225,35 +255,63 @@ void ServerSide::SyncValues(unsigned char socketnb, sf::IPAddress Address) m_client[socketnb].nick = std::string(buffer); m_client[socketnb].ready = false; + /////////////////// + // Test UDP Socket + /////////////////// + if (m_socketUDP.Send((const char*)&m_numplayers, 1, Address, m_client[m_numplayers].port) == sf::Socket::Done) + { + // Test UDP Socket Receive, 2s timeout + if (!RecvT(m_socketUDP, (char*)&init_number, 1, received, 2)) + errorUDP = true; + } + else + errorUDP = true; + // Check if the client has the game Socket.Receive((char *)&init_number, 1, received); - // Send to all connected clients - if (m_numplayers > 0) - { - unsigned char send = 0x10; - buffer_size = (int)m_client[socketnb].nick.size(); - for (int i=0; i < m_numplayers ; i++) - { - // Do not send to connecting player - if (i == socketnb) - continue; + delete[] buffer; - m_client[i].socket.Send((const char *)&send, 1); // Init new connection - m_client[i].socket.Send((const char *)&init_number, 1); // Send Game found ? - m_client[i].socket.Send((const char *)&buffer_size, 4); // Send client nickname - m_client[i].socket.Send(m_client[socketnb].nick.c_str(), buffer_size + 1); + if (!errorUDP) + { + // Send to all connected clients + if (m_numplayers > 0) + { + unsigned char send = 0x10; + buffer_size = (int)m_client[socketnb].nick.size(); + for (int i=0; i < m_numplayers ; i++) + { + // Do not send to connecting player + if (i == socketnb) + continue; + + m_client[i].socket.Send((const char *)&send, 1); // Init new connection + m_client[i].socket.Send((const char *)&init_number, 1); // Send Game found ? + m_client[i].socket.Send((const char *)&buffer_size, 4); // Send client nickname + m_client[i].socket.Send(m_client[socketnb].nick.c_str(), buffer_size + 1); + } } + + Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s:%d)\n"), + m_client[socketnb].nick.c_str(), Address.ToString().c_str(), m_client[m_numplayers].port) ); + + if (init_number != 0x1F) // Not Found + for (int i = 0; i < 4; i++) + Event->AppendText(_("WARNING : Game Not Found on Client Side !\n")); + + // UDP connecton successful + init_number = 0x16; + Socket.Send((const char *)&init_number, 1); + } + else // UDP Error, disconnect client + { + // UDP connecton failed + init_number = 0x17; + Socket.Send((const char *)&init_number, 1); + return false; } - Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s)\n"), - m_client[socketnb].nick.c_str(), Address.ToString().c_str()) ); - - if (init_number != 0x1F) // Not Found - for (int i = 0; i < 4; i++) - Event->AppendText(_("WARNING : Game Not Found on Client Side !\n")); - - delete[] buffer; + return true; } void ServerSide::Write(char socknb, const char *data, size_t size, long *ping) @@ -265,7 +323,7 @@ void ServerSide::Write(char socknb, const char *data, size_t size, long *ping) // Ask for ping unsigned char value = 0x15; size_t recv_size; - int four_bytes = 0x101A7FA6; + u32 four_bytes = 0x101A7FA6; Common::Timer timer; timer.Start(); @@ -287,23 +345,49 @@ void ServerSide::Write(char socknb, const char *data, size_t size, long *ping) m_client[socknb].socket.Send(data, size); } +void ServerSide::WriteUDP(char socknb, const char *data, size_t size) +{ + wxCriticalSectionLocker lock(m_CriticalSection); + + m_socketUDP.Send(data, size, m_client[socknb].address, m_client[socknb].port); +} + //-------------------------------- // CLIENT SIDE THREAD //-------------------------------- -ClientSide::ClientSide(NetPlay* netptr, sf::SocketTCP socket, std::string addr, std::string nick) +ClientSide::ClientSide(NetPlay* netptr, sf::SocketTCP socket, sf::SocketUDP socketUDP, std::string addr, std::string nick) : wxThread() { m_numplayers = 0; m_data_received = false; m_netmodel = 0; m_socket = socket; + m_socketUDP = socketUDP; + m_port = m_socketUDP.GetPort(); m_netptr = netptr; m_nick = nick; m_addr = addr; Event = new NetEvent(m_netptr); } +bool ClientSide::RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time) +{ + sf::SelectorUDP Selector; + sf::IPAddress addr; + Selector.Add(Socket); + + if (Selector.Wait(Time) > 0) + { + Socket.Receive(Data, Max, Recvd, addr); + return true; + } + else + { + return false; + } +} + void *ClientSide::Entry() { Event->AppendText(_("*Connection Request... ")); @@ -311,15 +395,31 @@ void *ClientSide::Entry() // If we get here, the connection is already accepted, however the game may be full if (SyncValues()) { - Event->AppendText(_("Connection successful !\n")); - Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s)\n*Game is : %s\n"), - m_hostnick.c_str(), m_addr.c_str(), m_selectedgame.c_str() ) ); - // Tell the server if the client has the game CheckGameFound(); + + // Check UDP connection + unsigned char value; + size_t val_sz; + m_socket.Receive((char *)&value, 1, val_sz); + + if (value == 0x16) // UDP connection successful + { + Event->AppendText(_("Connection successful !\n")); + Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s)\n*Game is : %s\n"), + m_hostnick.c_str(), m_addr.c_str(), m_selectedgame.c_str() ) ); + } + else + { + Event->AppendText(_("UDP Connection FAILED !\n" + "ERROR : Unable to establish UDP Connection, please Check UDP Port forwarding !")); + m_socket.Close(); + Event->SendEvent(HOST_ERROR); + return NULL; + } } - else { - // Post ServerFull event to GUI + else // Server is Full + { m_socket.Close(); Event->SendEvent(HOST_FULL); return NULL; @@ -385,15 +485,24 @@ void *ClientSide::Entry() bool ClientSide::SyncValues() { unsigned int buffer_size = (int)m_nick.size(); + unsigned char byterecv; + bool errorUDP; char *buffer = NULL; size_t recv_size; + unsigned short server_port; + std::string host = m_addr.substr(0, m_addr.find(':')); + TryParseInt(m_addr.substr(m_addr.find(':')+1).c_str(), (int *)&server_port); + // First, Read the init number : nbplayers (0-2) or server full (0x12) m_socket.Receive((char *)&m_numplayers, 1, recv_size); if (m_numplayers == 0x12) return false; m_socket.Receive((char *)&m_netmodel, 4, recv_size); + // Send client's UDP Port + m_socket.Send((const char *)&m_port, sizeof(short)); + // Send client's nickname m_socket.Send((const char *)&buffer_size, 4); m_socket.Send(m_nick.c_str(), buffer_size + 1); @@ -410,6 +519,18 @@ bool ClientSide::SyncValues() m_socket.Receive(buffer, buffer_size + 1, recv_size); m_hostnick = std::string(buffer); + /////////////////// + // Test UDP Socket + /////////////////// + if (m_socketUDP.Send((const char*)&m_numplayers, 1, host.c_str(), server_port) == sf::Socket::Done) + { + // Test UDP Socket Receive, 2s timeout + if (!RecvT(m_socketUDP, (char*)&byterecv, 1, recv_size, 2)) + errorUDP = true; + } + else + errorUDP = true; + delete[] buffer; return true; } @@ -460,3 +581,13 @@ void ClientSide::Write(const char *data, size_t size, long *ping) m_socket.Send(data, size); } +void ClientSide::WriteUDP(const char *data, size_t size) +{ + wxCriticalSectionLocker lock(m_CriticalSection); + + unsigned short server_port; + std::string host = m_addr.substr(0, m_addr.find(':')); + TryParseInt(m_addr.substr(m_addr.find(':')+1).c_str(), (int *)&server_port); + + m_socketUDP.Send(data, size, host.c_str(), server_port); +} diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 49e1cf546e..c319be57ac 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -20,7 +20,7 @@ /////////////////////// // Main Frame window -BEGIN_EVENT_TABLE(NetPlay, wxDialog) +BEGIN_EVENT_TABLE(NetPlay, wxFrame) EVT_BUTTON(ID_BUTTON_JOIN, NetPlay::OnJoin) EVT_BUTTON(ID_BUTTON_HOST, NetPlay::OnHost) @@ -38,7 +38,7 @@ BEGIN_EVENT_TABLE(NetPlay, wxDialog) END_EVENT_TABLE() NetPlay::NetPlay(wxWindow* parent, std::string GamePaths, std::string GameNames) : - wxDialog(parent, wxID_ANY, _T("Net Play"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~ wxMAXIMIZE_BOX ) + wxFrame(parent, wxID_ANY, _T("Net Play"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~ wxMAXIMIZE_BOX) { m_selectedGame = 'a'; m_hostaddr = 'a'; m_games = GameNames; m_paths = GamePaths; @@ -48,32 +48,62 @@ NetPlay::NetPlay(wxWindow* parent, std::string GamePaths, std::string GameNames) DrawGUI(); } +NetPlay::~NetPlay() +{ + ConfigIni.Load(CONFIG_FILE); + + ConfigIni.Set("Netplay", "Nickname", m_nick); + ConfigIni.Set("Netplay", "UsedPort", (int)m_port); + ConfigIni.Set("Netplay", "LastIP", m_address); + + ConfigIni.Save(CONFIG_FILE); +} + void NetPlay::OnJoin(wxCommandEvent& WXUNUSED(event)) { - wxString addr = m_ConAddr->GetValue(); - wxString host = addr.substr(0, addr.find(':')); - wxString port_str = addr.substr(addr.find(':')+1); - int port; TryParseInt(port_str.mb_str(), &port); - + unsigned short server_port; + + m_address = std::string(m_ConAddr->GetValue().mb_str()); m_nick = std::string(m_SetNick->GetValue().mb_str()); + + wxString host = m_address.substr(0, m_address.find(':')); + wxString port_str = m_address.substr(m_address.find(':')+1); + + TryParseInt(port_str.mb_str(), (int *)&server_port); // Server port + TryParseInt(m_SetPort->GetValue().mb_str(), (int *)&m_port); // User port + if (m_nick.size() > 255) m_nick = m_nick.substr(0 , 255); + SetTitle(_("Net Play : Connecting to Host...")); + // Create the client socket sf::SocketTCP sock_client; + sf::SocketUDP sock_client_UDP; - if (sock_client.Connect(port, (const char *)host.mb_str(), 1.5) == sf::Socket::Done) + if (sock_client.Connect(server_port, (const char*)host.mb_str(), 1.5) == sf::Socket::Done) { - m_sock_client = new ClientSide(this, sock_client, std::string(addr.mb_str()), m_nick); - m_sock_client->Create(); - m_sock_client->Run(); + // Try to Bind the UDP Socket + if (sock_client_UDP.Bind(m_port)) + { + m_sock_client = new ClientSide(this, sock_client, sock_client_UDP, m_address, m_nick); + m_sock_client->Create(); + m_sock_client->Run(); - // Create the GUI - m_isHosting = false; - DrawNetWindow(); + // Create the GUI + m_isHosting = false; + DrawNetWindow(); + } + else + { + SetTitle(_("Net Play")); + PanicAlert("Can't Bind UDP socket on the specified Port: %d ! \n" + "Make sure port is forwarded and not in use !", m_port); + } } else { + SetTitle(_("Net Play")); PanicAlert("Can't connect to the specified IP Address ! \nMake sure Hosting port is forwarded !"); } } @@ -82,26 +112,30 @@ void NetPlay::OnHost(wxCommandEvent& WXUNUSED(event)) { TryParseInt(m_SetPort->GetValue().mb_str(), (int*)&m_port); + m_nick = std::string(m_SetNick->GetValue().mb_str()); + if (m_GameList->GetSelection() == wxNOT_FOUND) { PanicAlert("No Game Selected ! Please select a Game..."); return; } - if (!m_SetPort->GetValue().size() || m_port < 100 || m_port > 65535) { + if (!m_SetPort->GetValue().size() || m_port < 1000 || m_port > 65535) { PanicAlert("Bad Port entered (%d) ! Please enter a working socket port...", m_port); return; } - - m_nick = std::string(m_SetNick->GetValue().mb_str()); - if (m_nick.size() > 255) m_nick = m_nick.substr(0 , 255); + if (m_nick.size() > 255) + m_nick = m_nick.substr(0 , 255); m_NetModel = m_NetMode->GetSelection(); m_selectedGame = std::string(m_GameList_str[m_GameList->GetSelection()].mb_str()); - m_numClients = 0; - // Start the listening socket - if (m_listensocket.Listen(m_port)) + // Create the listening socket + sf::SocketTCP sock_server; + sf::SocketUDP sock_server_UDP; + + // Start the listening socket and bind UDP socket port + if (sock_server.Listen(m_port) && sock_server_UDP.Bind(m_port)) { - m_sock_server = new ServerSide(this, m_listensocket, m_NetModel, m_nick); + m_sock_server = new ServerSide(this, sock_server, sock_server_UDP, m_NetModel, m_nick); m_sock_server->Create(); m_sock_server->Run(); @@ -137,27 +171,27 @@ void NetPlay::DrawGUI() } netmodes_str.Add(wxT("P2P Versus (2 players, faster)")); - // TODO : - // netmodes_str.Add(wxT("Server Mode (4 players, slower)")); + // TODO : netmodes_str.Add(wxT("Server Mode (4 players, slower)")); + + wxPanel *panel = new wxPanel(this); // Tabs - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); + m_Notebook = new wxNotebook(panel, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); m_Tab_Connect = new wxPanel(m_Notebook, ID_TAB_CONN, wxDefaultPosition, wxDefaultSize); m_Notebook->AddPage(m_Tab_Connect, wxT("Connect")); m_Tab_Host = new wxPanel(m_Notebook, ID_TAB_HOST, wxDefaultPosition, wxDefaultSize); m_Notebook->AddPage(m_Tab_Host, wxT("Host")); - // Nickname setting - m_SetNick_text = new wxStaticText(this, ID_SETNICK_TXT, wxT(" Nickname : "), wxDefaultPosition, wxDefaultSize); - m_SetNick = new wxTextCtrl(this, ID_SETNICK, wxT("Mingebag"), wxDefaultPosition, wxDefaultSize, 0); - m_NetMode = new wxChoice(this, ID_NETMODE, wxDefaultPosition, wxDefaultSize, netmodes_str, 0, wxDefaultValidator); - m_NetMode->SetSelection(0); + // Tow window, Nickname & Port settings + m_SetNick_text = new wxStaticText(panel, wxID_ANY, wxT(" Nickname : "), wxDefaultPosition, wxDefaultSize); + m_SetNick = new wxTextCtrl(panel, ID_SETNICK, wxT("LOLWUT!"), wxDefaultPosition, wxDefaultSize); + m_SetPort_text = new wxStaticText(panel, wxID_ANY, wxT(" Port to Use : "), wxDefaultPosition, wxDefaultSize); + m_SetPort = new wxTextCtrl(panel, ID_SETPORT, wxT("12345"), wxDefaultPosition, wxDefaultSize); // CONNECTION TAB - m_ConAddr_text = new wxStaticText(m_Tab_Connect, ID_CONNADDR_TXT, wxT(" IP Address :"), wxDefaultPosition, wxDefaultSize); + m_ConAddr_text = new wxStaticText(m_Tab_Connect, wxID_ANY, wxT(" IP Address :"), wxDefaultPosition, wxDefaultSize); m_ConAddr = new wxTextCtrl(m_Tab_Connect, ID_CONNADDR, wxT("127.0.0.1:12345"), wxDefaultPosition, wxSize(250,20), 0); m_UseRandomPort = new wxCheckBox(m_Tab_Connect, ID_USE_RANDOMPORT, wxT("Use random client port for connection")); - m_UseRandomPort->SetValue(true); m_UseRandomPort->Enable(false); m_JoinGame = new wxButton(m_Tab_Connect, ID_BUTTON_JOIN, wxT("Connect"), wxDefaultPosition, wxDefaultSize); // Sizers CONNECT @@ -165,7 +199,7 @@ void NetPlay::DrawGUI() wxBoxSizer* sConnectSizer = new wxBoxSizer(wxVERTICAL); sConnectTop->Add(m_ConAddr_text, 0, wxALL|wxALIGN_CENTER, 5); - sConnectTop->Add(m_ConAddr, 3, wxALL|wxEXPAND, 5); + sConnectTop->Add(m_ConAddr, 1, wxALL|wxEXPAND, 5); sConnectTop->Add(m_JoinGame, 0, wxALL|wxALIGN_RIGHT, 5); sConnectSizer->Add(sConnectTop, 0, wxALL|wxEXPAND, 5); sConnectSizer->Add(m_UseRandomPort, 0, wxALL|wxALIGN_CENTER, 5); @@ -173,44 +207,57 @@ void NetPlay::DrawGUI() m_Tab_Connect->SetSizer(sConnectSizer); // HOSTING TAB - m_SetPort_text = new wxStaticText(m_Tab_Host, ID_SETPORT_TXT, wxT(" Use Port : "), wxDefaultPosition, wxDefaultSize); - m_SetPort = new wxTextCtrl(m_Tab_Host, ID_SETPORT, wxT("12345"), wxDefaultPosition, wxDefaultSize, 0); - m_GameList_text = new wxStaticText(m_Tab_Host, ID_GAMELIST_TXT, wxT("Warning: Use a forwarded port ! Select Game and press Host :"), wxDefaultPosition, wxDefaultSize); + m_GameList_text = new wxStaticText(m_Tab_Host, wxID_ANY, + wxT("Warning: Use a forwarded port ! Select Game and press Host :"), wxDefaultPosition, wxDefaultSize); m_GameList = new wxListBox(m_Tab_Host, ID_GAMELIST, wxDefaultPosition, wxDefaultSize, m_GameList_str, wxLB_SINGLE | wxLB_NEEDED_SB); m_HostGame = new wxButton(m_Tab_Host, ID_BUTTON_HOST, wxT("Host"), wxDefaultPosition, wxDefaultSize); + m_NetMode = new wxChoice(m_Tab_Host, ID_NETMODE, wxDefaultPosition, wxDefaultSize, netmodes_str, 0, wxDefaultValidator); + m_NetMode->SetSelection(0); // Sizers HOST wxBoxSizer *sHostBox = new wxBoxSizer(wxVERTICAL); - wxBoxSizer *sHostTop = new wxBoxSizer(wxHORIZONTAL); - wxBoxSizer *sHostMid = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer *sHostBottom = new wxBoxSizer(wxHORIZONTAL); - sHostTop->Add(m_SetPort_text, 0, wxALL|wxALIGN_CENTER, 5); - sHostTop->Add(m_SetPort, 1, wxALL|wxEXPAND, 5); - sHostMid->Add(m_GameList, 1, wxALL|wxEXPAND, 5); + sHostBottom->Add(m_NetMode, 0, wxALL|wxALIGN_CENTER, 5); + sHostBottom->AddStretchSpacer(); + sHostBottom->Add(m_HostGame, 0, wxALL, 10); sHostBox->Add(m_GameList_text, 0, wxALL|wxALIGN_CENTER, 5); - sHostBox->Add(sHostTop, 0, wxALL|wxEXPAND, 1); - sHostBox->Add(sHostMid, 1, wxALL|wxEXPAND, 1); - sHostBox->Add(m_HostGame, 0, wxALL|wxALIGN_RIGHT, 10); + sHostBox->Add(m_GameList, 1, wxALL|wxEXPAND, 6); + sHostBox->Add(sHostBottom, 0, wxALL|wxEXPAND, 1); m_Tab_Host->SetSizer(sHostBox); - sHostBox->Layout(); - // main sizers + // Main sizers wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL); wxBoxSizer* sMain_top = new wxBoxSizer(wxHORIZONTAL); sMain_top->Add(m_SetNick_text, 0, wxALL|wxALIGN_CENTER, 3); - sMain_top->Add(m_SetNick, 0, wxALL, 3); - sMain_top->AddStretchSpacer(1); - sMain_top->Add(m_NetMode, 0, wxALL|wxALIGN_RIGHT, 3); + sMain_top->Add(m_SetNick, 1, wxALL|wxALIGN_CENTER, 3); + sMain_top->AddStretchSpacer(); + sMain_top->Add(m_SetPort_text, 0, wxALL|wxALIGN_CENTER, 3); + sMain_top->Add(m_SetPort, 1, wxALL|wxALIGN_CENTER, 3); sMain->Add(sMain_top, 0, wxALL|wxEXPAND, 5); sMain->Add(m_Notebook, 1, wxALL|wxEXPAND, 5); - SetSizerAndFit(sMain); - Center(); Layout(); Show(); + // Adjust panel to window's size, and set resizing minimum boundaries + panel->SetSizerAndFit(sMain); + sMain->SetSizeHints((wxWindow*)this); + + if (ConfigIni.Load(CONFIG_FILE)) + { + ConfigIni.Get("Netplay", "Nickname", &m_nick, "Unnamed"); + ConfigIni.Get("Netplay", "UsedPort", (int*)&m_port, 12345); + ConfigIni.Get("Netplay", "LastIP", &m_address, "127.0.0.1:54321"); + + m_SetNick->SetValue(_(m_nick.c_str())); + m_SetPort->SetValue(wxString::Format(wxT("%d"), m_port)); + m_ConAddr->SetValue(_(m_address.c_str())); + } + + Center(); Show(); } void NetPlay::DrawNetWindow() @@ -218,33 +265,31 @@ void NetPlay::DrawNetWindow() // Remove everything from the precedent GUI :D DestroyChildren(); - SetTitle(_("Connection Window")); + SetTitle(_("Net Play : Connection Window")); + wxPanel *panel = new wxPanel(this); wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL); wxBoxSizer* sTop = new wxBoxSizer(wxVERTICAL); wxBoxSizer* sBottom = new wxBoxSizer(wxHORIZONTAL); - m_Game_str = new wxButton(this, wxID_ANY, wxT(" Game : "), wxDefaultPosition, wxSize(400, 25), wxBU_LEFT); + m_Game_str = new wxButton(panel, wxID_ANY, wxT(" Game : "), wxDefaultPosition, wxSize(400, 25), wxBU_LEFT); m_Game_str->Disable(); - m_Logging = new wxTextCtrl(this, ID_LOGGING_TXT, wxEmptyString, + m_Logging = new wxTextCtrl(panel, ID_LOGGING_TXT, wxEmptyString, wxDefaultPosition, wxSize(400, 250), wxTE_RICH2 | wxTE_MULTILINE | wxTE_READONLY); - // Too bad this doesn't work... - //m_Logging->SetDefaultStyle(wxTextAttr(*wxRED)); - - m_Chat = new wxTextCtrl(this, ID_CHAT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); - m_Chat_ok = new wxButton(this, ID_BUTTON_CHAT, wxT("Send"));; + m_Chat = new wxTextCtrl(panel, ID_CHAT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); + m_Chat_ok = new wxButton(panel, ID_BUTTON_CHAT, wxT("Send"));; - m_Ready = new wxCheckBox(this, ID_READY, wxT("Click here when ready"), wxDefaultPosition, wxDefaultSize, 0); - m_RecordGame = new wxCheckBox(this, ID_RECORD, wxT("Record Game Input"), wxDefaultPosition, wxDefaultSize, 0); + m_Ready = new wxCheckBox(panel, ID_READY, wxT("Click here when ready"), wxDefaultPosition, wxDefaultSize, 0); + m_RecordGame = new wxCheckBox(panel, ID_RECORD, wxT("Record Game Input"), wxDefaultPosition, wxDefaultSize, 0); // TODO: Fix the recording ? m_RecordGame->Disable(); - m_ConInfo_text = new wxStaticText(this, ID_CONNINFO_TXT, wxT(" Fps : 0 | Ping : 00 ms")); - m_GetPing = new wxButton(this, ID_BUTTON_GETPING, wxT("Ping"), wxDefaultPosition, wxDefaultSize); - m_Disconnect = new wxButton(this, ID_BUTTON_QUIT, wxT("Disconnect"), wxDefaultPosition, wxDefaultSize); + m_ConInfo_text = new wxStaticText(panel, ID_CONNINFO_TXT, wxT(" Fps : 0 | Ping : 00 ms")); + m_GetPing = new wxButton(panel, ID_BUTTON_GETPING, wxT("Ping"), wxDefaultPosition, wxDefaultSize); + m_Disconnect = new wxButton(panel, ID_BUTTON_QUIT, wxT("Disconnect"), wxDefaultPosition, wxDefaultSize); wxBoxSizer* sChat = new wxBoxSizer(wxHORIZONTAL); @@ -274,10 +319,10 @@ void NetPlay::DrawNetWindow() if (m_isHosting) { - m_wtfismyip = new wxButton(this, ID_BUTTON_GETIP, wxT("What is my IP")); - m_ChangeGame = new wxButton(this, ID_CHANGEGAME, wxT("Change Game")); + m_wtfismyip = new wxButton(panel, ID_BUTTON_GETIP, wxT("What is my IP")); + m_ChangeGame = new wxButton(panel, ID_CHANGEGAME, wxT("Change Game")); - wxStaticBoxSizer* sBottom3 = new wxStaticBoxSizer(wxVERTICAL, this, _("Host")); + wxStaticBoxSizer* sBottom3 = new wxStaticBoxSizer(wxVERTICAL, panel, _("Host")); sBottom3->Add(m_ChangeGame, 0, wxALL | wxEXPAND, 5); sBottom3->Add(m_wtfismyip, 0, wxALL | wxEXPAND, 5); @@ -289,18 +334,19 @@ void NetPlay::DrawNetWindow() sMain->Add(sTop, 1, wxALL | wxEXPAND, 5); sMain->Add(sBottom, 0, wxALL | wxEXPAND | wxALIGN_CENTER, 2); - SetSizerAndFit(sMain); - Center(); Layout(); + panel->SetSizerAndFit(sMain); + sMain->SetSizeHints((wxWindow*)this); + Show(); } -void NetPlay::UpdateNetWindow(bool update_infos, wxString infos/*int fps, float ping, int frame_delay*/) +// String of the type : FPSxPINGxFRAME_DELAY +void NetPlay::UpdateNetWindow(bool update_infos, wxString infos) { std::vector str_arr; if (update_infos) { - // String of the type : FPSxPINGxFRAME_DELAY SplitString(std::string(infos.mb_str()), "x", str_arr); m_ConInfo_text->SetLabel @@ -346,9 +392,10 @@ void NetPlay::OnGUIEvent(wxCommandEvent& event) m_sock_server->Write(i, buffer.c_str(), buffer_size + 1); } } - + m_Logging->AppendText(wxString::FromAscii(buffer.c_str())); + // Everyone is ready if (m_ready && m_clients_ready) LoadGame(); } @@ -388,7 +435,6 @@ void NetPlay::OnGUIEvent(wxCommandEvent& event) if (m_numClients == 0) return; - // TODO : This is not designed for > 2 players long ping[3] = {0}; float fping; @@ -442,8 +488,7 @@ void NetPlay::OnGUIEvent(wxCommandEvent& event) m_Chat->Clear(); - // We should maybe wait for the server to send it... - // but we write it anyway :p + // Do not wait for the server, just write as soon as sent m_Logging->AppendText(chat_str); break; diff --git a/Source/Core/DolphinWX/Src/NetWindow.h b/Source/Core/DolphinWX/Src/NetWindow.h index e4ebbfb2ad..69f6a68ded 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.h +++ b/Source/Core/DolphinWX/Src/NetWindow.h @@ -43,6 +43,10 @@ #define NET_DEBUG #endif +// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay, +// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping) +// #define USE_TCP + class NetPlay; struct Netpads { @@ -53,6 +57,8 @@ struct Netpads { struct Clients { std::string nick; sf::SocketTCP socket; + unsigned short port; + sf::IPAddress address; bool ready; }; @@ -72,16 +78,18 @@ class NetEvent class ServerSide : public wxThread { public: - ServerSide(NetPlay* netptr, sf::SocketTCP socket, int netmodel, std::string nick); + ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick); ~ServerSide() {}; virtual void *Entry(); void Write(char socknb, const char *data, size_t size, long *ping=NULL); + void WriteUDP(char socknb, const char *data, size_t size); bool isNewPadData(u32 *netValues, bool current, char client=0); private: - void SyncValues(unsigned char, sf::IPAddress); + bool SyncValues(unsigned char, sf::IPAddress); + bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0); char GetSocket(sf::SocketTCP Socket); void OnServerData(char sock, unsigned char data); void IsEveryoneReady(); @@ -89,7 +97,7 @@ class ServerSide : public wxThread NetPlay *m_netptr; NetEvent *Event; - u32 m_netvalues[3][2]; + u32 m_netvalues[3][3]; bool m_data_received; // New Pad data received ? unsigned char m_numplayers; @@ -99,6 +107,7 @@ class ServerSide : public wxThread Clients m_client[3]; // Connected client objects sf::SelectorTCP m_selector; sf::SocketTCP m_socket; // Server 'listening' socket + sf::SocketUDP m_socketUDP; wxCriticalSection m_CriticalSection; }; @@ -106,23 +115,25 @@ class ServerSide : public wxThread class ClientSide : public wxThread { public: - ClientSide(NetPlay* netptr, sf::SocketTCP socket, std::string addr, std::string nick); + ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick); ~ClientSide() {} virtual void *Entry(); void Write(const char *data, size_t size, long *ping=NULL); + void WriteUDP(const char *data, size_t size); bool isNewPadData(u32 *netValues, bool current, bool isVersus=true); private: bool SyncValues(); void CheckGameFound(); void OnClientData(unsigned char data); + bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0); NetPlay *m_netptr; NetEvent *Event; - u32 m_netvalues[3][2]; + u32 m_netvalues[3][3]; bool m_data_received; // New Pad data received ? unsigned char m_numplayers; @@ -133,16 +144,18 @@ class ClientSide : public wxThread sf::SelectorTCP m_selector; sf::SocketTCP m_socket; // Client I/O socket + sf::SocketUDP m_socketUDP; + unsigned short m_port; std::string m_addr; // Contains the server addr wxCriticalSection m_CriticalSection; }; -class NetPlay : public wxDialog +class NetPlay : public wxFrame { public: NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = ""); - ~NetPlay() {} + ~NetPlay(); void UpdateNetWindow(bool update_infos, wxString=wxT("NULL")); void AppendText(const wxString text) { m_Logging->AppendText(text); } @@ -151,9 +164,10 @@ class NetPlay : public wxDialog bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues); void ChangeSelectedGame(std::string game); void IsGameFound(unsigned char*, std::string); - bool IsReady() { wxCriticalSectionLocker lock(m_critical); return m_ready; } std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; } + void LoadGame(); + protected: // Protects our vars from being fuxored by threads wxCriticalSection m_critical; @@ -171,10 +185,9 @@ class NetPlay : public wxDialog void OnJoin(wxCommandEvent& event); void OnHost(wxCommandEvent& event); - void LoadGame(); - // Net play vars (used ingame) int m_frame; + int m_lastframe; Common::Timer m_timer; int m_loopframe; int m_frameDelay; @@ -192,12 +205,13 @@ class NetPlay : public wxDialog int m_NetModel; // Using P2P model (0) or Server model (1) int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients + std::string m_address; // The address entered into connection box unsigned short m_port; Netpads m_pads[4]; // this struct is used to save synced pad values + IniFile ConfigIni; // Sockets objects - sf::SocketTCP m_listensocket; ServerSide *m_sock_server; ClientSide *m_sock_client; @@ -268,15 +282,11 @@ enum ID_BUTTON_JOIN, ID_NETMODE, ID_GAMELIST, - ID_GAMELIST_TXT, ID_LOGGING_TXT, ID_CHAT, - ID_SETNICK_TXT, ID_SETNICK, ID_SETPORT, - ID_SETPORT_TXT, ID_CONNADDR, - ID_CONNADDR_TXT, ID_CONNINFO_TXT, ID_USE_RANDOMPORT, ID_BUTTON_GETPING, diff --git a/Source/Core/DolphinWX/resources/Dolphin.c b/Source/Core/DolphinWX/resources/Dolphin.c index 2c9646eabb..435f5a0670 100644 --- a/Source/Core/DolphinWX/resources/Dolphin.c +++ b/Source/Core/DolphinWX/resources/Dolphin.c @@ -1,288 +1,514 @@ -static const unsigned char dolphin_png[] = { -0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, -0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, -0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x91, 0x68, 0x36, 0x00, 0x00, 0x00, -0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, -0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x0a, 0x4f, 0x69, 0x43, -0x43, 0x50, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x20, -0x49, 0x43, 0x43, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, -0x00, 0x78, 0xda, 0x9d, 0x53, 0x67, 0x54, 0x53, 0xe9, 0x16, 0x3d, 0xf7, -0xde, 0xf4, 0x42, 0x4b, 0x88, 0x80, 0x94, 0x4b, 0x6f, 0x52, 0x15, 0x08, -0x20, 0x52, 0x42, 0x8b, 0x80, 0x14, 0x91, 0x26, 0x2a, 0x21, 0x09, 0x10, -0x4a, 0x88, 0x21, 0xa1, 0xd9, 0x15, 0x51, 0xc1, 0x11, 0x45, 0x45, 0x04, -0x1b, 0xc8, 0xa0, 0x88, 0x03, 0x8e, 0x8e, 0x80, 0x8c, 0x15, 0x51, 0x2c, -0x0c, 0x8a, 0x0a, 0xd8, 0x07, 0xe4, 0x21, 0xa2, 0x8e, 0x83, 0xa3, 0x88, -0x8a, 0xca, 0xfb, 0xe1, 0x7b, 0xa3, 0x6b, 0xd6, 0xbc, 0xf7, 0xe6, 0xcd, -0xfe, 0xb5, 0xd7, 0x3e, 0xe7, 0xac, 0xf3, 0x9d, 0xb3, 0xcf, 0x07, 0xc0, -0x08, 0x0c, 0x96, 0x48, 0x33, 0x51, 0x35, 0x80, 0x0c, 0xa9, 0x42, 0x1e, -0x11, 0xe0, 0x83, 0xc7, 0xc4, 0xc6, 0xe1, 0xe4, 0x2e, 0x40, 0x81, 0x0a, -0x24, 0x70, 0x00, 0x10, 0x08, 0xb3, 0x64, 0x21, 0x73, 0xfd, 0x23, 0x01, -0x00, 0xf8, 0x7e, 0x3c, 0x3c, 0x2b, 0x22, 0xc0, 0x07, 0xbe, 0x00, 0x01, -0x78, 0xd3, 0x0b, 0x08, 0x00, 0xc0, 0x4d, 0x9b, 0xc0, 0x30, 0x1c, 0x87, -0xff, 0x0f, 0xea, 0x42, 0x99, 0x5c, 0x01, 0x80, 0x84, 0x01, 0xc0, 0x74, -0x91, 0x38, 0x4b, 0x08, 0x80, 0x14, 0x00, 0x40, 0x7a, 0x8e, 0x42, 0xa6, -0x00, 0x40, 0x46, 0x01, 0x80, 0x9d, 0x98, 0x26, 0x53, 0x00, 0xa0, 0x04, -0x00, 0x60, 0xcb, 0x63, 0x62, 0xe3, 0x00, 0x50, 0x2d, 0x00, 0x60, 0x27, -0x7f, 0xe6, 0xd3, 0x00, 0x80, 0x9d, 0xf8, 0x99, 0x7b, 0x01, 0x00, 0x5b, -0x94, 0x21, 0x15, 0x01, 0xa0, 0x91, 0x00, 0x20, 0x13, 0x65, 0x88, 0x44, -0x00, 0x68, 0x3b, 0x00, 0xac, 0xcf, 0x56, 0x8a, 0x45, 0x00, 0x58, 0x30, -0x00, 0x14, 0x66, 0x4b, 0xc4, 0x39, 0x00, 0xd8, 0x2d, 0x00, 0x30, 0x49, -0x57, 0x66, 0x48, 0x00, 0xb0, 0xb7, 0x00, 0xc0, 0xce, 0x10, 0x0b, 0xb2, -0x00, 0x08, 0x0c, 0x00, 0x30, 0x51, 0x88, 0x85, 0x29, 0x00, 0x04, 0x7b, -0x00, 0x60, 0xc8, 0x23, 0x23, 0x78, 0x00, 0x84, 0x99, 0x00, 0x14, 0x46, -0xf2, 0x57, 0x3c, 0xf1, 0x2b, 0xae, 0x10, 0xe7, 0x2a, 0x00, 0x00, 0x78, -0x99, 0xb2, 0x3c, 0xb9, 0x24, 0x39, 0x45, 0x81, 0x5b, 0x08, 0x2d, 0x71, -0x07, 0x57, 0x57, 0x2e, 0x1e, 0x28, 0xce, 0x49, 0x17, 0x2b, 0x14, 0x36, -0x61, 0x02, 0x61, 0x9a, 0x40, 0x2e, 0xc2, 0x79, 0x99, 0x19, 0x32, 0x81, -0x34, 0x0f, 0xe0, 0xf3, 0xcc, 0x00, 0x00, 0xa0, 0x91, 0x15, 0x11, 0xe0, -0x83, 0xf3, 0xfd, 0x78, 0xce, 0x0e, 0xae, 0xce, 0xce, 0x36, 0x8e, 0xb6, -0x0e, 0x5f, 0x2d, 0xea, 0xbf, 0x06, 0xff, 0x22, 0x62, 0x62, 0xe3, 0xfe, -0xe5, 0xcf, 0xab, 0x70, 0x40, 0x00, 0x00, 0xe1, 0x74, 0x7e, 0xd1, 0xfe, -0x2c, 0x2f, 0xb3, 0x1a, 0x80, 0x3b, 0x06, 0x80, 0x6d, 0xfe, 0xa2, 0x25, -0xee, 0x04, 0x68, 0x5e, 0x0b, 0xa0, 0x75, 0xf7, 0x8b, 0x66, 0xb2, 0x0f, -0x40, 0xb5, 0x00, 0xa0, 0xe9, 0xda, 0x57, 0xf3, 0x70, 0xf8, 0x7e, 0x3c, -0x3c, 0x45, 0xa1, 0x90, 0xb9, 0xd9, 0xd9, 0xe5, 0xe4, 0xe4, 0xd8, 0x4a, -0xc4, 0x42, 0x5b, 0x61, 0xca, 0x57, 0x7d, 0xfe, 0x67, 0xc2, 0x5f, 0xc0, -0x57, 0xfd, 0x6c, 0xf9, 0x7e, 0x3c, 0xfc, 0xf7, 0xf5, 0xe0, 0xbe, 0xe2, -0x24, 0x81, 0x32, 0x5d, 0x81, 0x47, 0x04, 0xf8, 0xe0, 0xc2, 0xcc, 0xf4, -0x4c, 0xa5, 0x1c, 0xcf, 0x92, 0x09, 0x84, 0x62, 0xdc, 0xe6, 0x8f, 0x47, -0xfc, 0xb7, 0x0b, 0xff, 0xfc, 0x1d, 0xd3, 0x22, 0xc4, 0x49, 0x62, 0xb9, -0x58, 0x2a, 0x14, 0xe3, 0x51, 0x12, 0x71, 0x8e, 0x44, 0x9a, 0x8c, 0xf3, -0x32, 0xa5, 0x22, 0x89, 0x42, 0x92, 0x29, 0xc5, 0x25, 0xd2, 0xff, 0x64, -0xe2, 0xdf, 0x2c, 0xfb, 0x03, 0x3e, 0xdf, 0x35, 0x00, 0xb0, 0x6a, 0x3e, -0x01, 0x7b, 0x91, 0x2d, 0xa8, 0x5d, 0x63, 0x03, 0xf6, 0x4b, 0x27, 0x10, -0x58, 0x74, 0xc0, 0xe2, 0xf7, 0x00, 0x00, 0xf2, 0xbb, 0x6f, 0xc1, 0xd4, -0x28, 0x08, 0x03, 0x80, 0x68, 0x83, 0xe1, 0xcf, 0x77, 0xff, 0xef, 0x3f, -0xfd, 0x47, 0xa0, 0x25, 0x00, 0x80, 0x66, 0x49, 0x92, 0x71, 0x00, 0x00, -0x5e, 0x44, 0x24, 0x2e, 0x54, 0xca, 0xb3, 0x3f, 0xc7, 0x08, 0x00, 0x00, -0x44, 0xa0, 0x81, 0x2a, 0xb0, 0x41, 0x1b, 0xf4, 0xc1, 0x18, 0x2c, 0xc0, -0x06, 0x1c, 0xc1, 0x05, 0xdc, 0xc1, 0x0b, 0xfc, 0x60, 0x36, 0x84, 0x42, -0x24, 0xc4, 0xc2, 0x42, 0x10, 0x42, 0x0a, 0x64, 0x80, 0x1c, 0x72, 0x60, -0x29, 0xac, 0x82, 0x42, 0x28, 0x86, 0xcd, 0xb0, 0x1d, 0x2a, 0x60, 0x2f, -0xd4, 0x40, 0x1d, 0x34, 0xc0, 0x51, 0x68, 0x86, 0x93, 0x70, 0x0e, 0x2e, -0xc2, 0x55, 0xb8, 0x0e, 0x3d, 0x70, 0x0f, 0xfa, 0x61, 0x08, 0x9e, 0xc1, -0x28, 0xbc, 0x81, 0x09, 0x04, 0x41, 0xc8, 0x08, 0x13, 0x61, 0x21, 0xda, -0x88, 0x01, 0x62, 0x8a, 0x58, 0x23, 0x8e, 0x08, 0x17, 0x99, 0x85, 0xf8, -0x21, 0xc1, 0x48, 0x04, 0x12, 0x8b, 0x24, 0x20, 0xc9, 0x88, 0x14, 0x51, -0x22, 0x4b, 0x91, 0x35, 0x48, 0x31, 0x52, 0x8a, 0x54, 0x20, 0x55, 0x48, -0x1d, 0xf2, 0x3d, 0x72, 0x02, 0x39, 0x87, 0x5c, 0x46, 0xba, 0x91, 0x3b, -0xc8, 0x00, 0x32, 0x82, 0xfc, 0x86, 0xbc, 0x47, 0x31, 0x94, 0x81, 0xb2, -0x51, 0x3d, 0xd4, 0x0c, 0xb5, 0x43, 0xb9, 0xa8, 0x37, 0x1a, 0x84, 0x46, -0xa2, 0x0b, 0xd0, 0x64, 0x74, 0x31, 0x9a, 0x8f, 0x16, 0xa0, 0x9b, 0xd0, -0x72, 0xb4, 0x1a, 0x3d, 0x8c, 0x36, 0xa1, 0xe7, 0xd0, 0xab, 0x68, 0x0f, -0xda, 0x8f, 0x3e, 0x43, 0xc7, 0x30, 0xc0, 0xe8, 0x18, 0x07, 0x33, 0xc4, -0x6c, 0x30, 0x2e, 0xc6, 0xc3, 0x42, 0xb1, 0x38, 0x2c, 0x09, 0x93, 0x63, -0xcb, 0xb1, 0x22, 0xac, 0x0c, 0xab, 0xc6, 0x1a, 0xb0, 0x56, 0xac, 0x03, -0xbb, 0x89, 0xf5, 0x63, 0xcf, 0xb1, 0x77, 0x04, 0x12, 0x81, 0x45, 0xc0, -0x09, 0x36, 0x04, 0x77, 0x42, 0x20, 0x61, 0x1e, 0x41, 0x48, 0x58, 0x4c, -0x58, 0x4e, 0xd8, 0x48, 0xa8, 0x20, 0x1c, 0x24, 0x34, 0x11, 0xda, 0x09, -0x37, 0x09, 0x03, 0x84, 0x51, 0xc2, 0x27, 0x22, 0x93, 0xa8, 0x4b, 0xb4, -0x26, 0xba, 0x11, 0xf9, 0xc4, 0x18, 0x62, 0x32, 0x31, 0x87, 0x58, 0x48, -0x2c, 0x23, 0xd6, 0x12, 0x8f, 0x13, 0x2f, 0x10, 0x7b, 0x88, 0x43, 0xc4, -0x37, 0x24, 0x12, 0x89, 0x43, 0x32, 0x27, 0xb9, 0x90, 0x02, 0x49, 0xb1, -0xa4, 0x54, 0xd2, 0x12, 0xd2, 0x46, 0xd2, 0x6e, 0x52, 0x23, 0xe9, 0x2c, -0xa9, 0x9b, 0x34, 0x48, 0x1a, 0x23, 0x93, 0xc9, 0xda, 0x64, 0x6b, 0xb2, -0x07, 0x39, 0x94, 0x2c, 0x20, 0x2b, 0xc8, 0x85, 0xe4, 0x9d, 0xe4, 0xc3, -0xe4, 0x33, 0xe4, 0x1b, 0xe4, 0x21, 0xf2, 0x5b, 0x0a, 0x9d, 0x62, 0x40, -0x71, 0xa4, 0xf8, 0x53, 0xe2, 0x28, 0x52, 0xca, 0x6a, 0x4a, 0x19, 0xe5, -0x10, 0xe5, 0x34, 0xe5, 0x06, 0x65, 0x98, 0x32, 0x41, 0x55, 0xa3, 0x9a, -0x52, 0xdd, 0xa8, 0xa1, 0x54, 0x11, 0x35, 0x8f, 0x5a, 0x42, 0xad, 0xa1, -0xb6, 0x52, 0xaf, 0x51, 0x87, 0xa8, 0x13, 0x34, 0x75, 0x9a, 0x39, 0xcd, -0x83, 0x16, 0x49, 0x4b, 0xa5, 0xad, 0xa2, 0x95, 0xd3, 0x1a, 0x68, 0x17, -0x68, 0xf7, 0x69, 0xaf, 0xe8, 0x74, 0xba, 0x11, 0xdd, 0x95, 0x1e, 0x4e, -0x97, 0xd0, 0x57, 0xd2, 0xcb, 0xe9, 0x47, 0xe8, 0x97, 0xe8, 0x03, 0xf4, -0x77, 0x0c, 0x0d, 0x86, 0x15, 0x83, 0xc7, 0x88, 0x67, 0x28, 0x19, 0x9b, -0x18, 0x07, 0x18, 0x67, 0x19, 0x77, 0x18, 0xaf, 0x98, 0x4c, 0xa6, 0x19, -0xd3, 0x8b, 0x19, 0xc7, 0x54, 0x30, 0x37, 0x31, 0xeb, 0x98, 0xe7, 0x99, -0x0f, 0x99, 0x6f, 0x55, 0x58, 0x2a, 0xb6, 0x2a, 0x7c, 0x15, 0x91, 0xca, -0x0a, 0x95, 0x4a, 0x95, 0x26, 0x95, 0x1b, 0x2a, 0x2f, 0x54, 0xa9, 0xaa, -0xa6, 0xaa, 0xde, 0xaa, 0x0b, 0x55, 0xf3, 0x55, 0xcb, 0x54, 0x8f, 0xa9, -0x5e, 0x53, 0x7d, 0xae, 0x46, 0x55, 0x33, 0x53, 0xe3, 0xa9, 0x09, 0xd4, -0x96, 0xab, 0x55, 0xaa, 0x9d, 0x50, 0xeb, 0x53, 0x1b, 0x53, 0x67, 0xa9, -0x3b, 0xa8, 0x87, 0xaa, 0x67, 0xa8, 0x6f, 0x54, 0x3f, 0xa4, 0x7e, 0x59, -0xfd, 0x89, 0x06, 0x59, 0xc3, 0x4c, 0xc3, 0x4f, 0x43, 0xa4, 0x51, 0xa0, -0xb1, 0x5f, 0xe3, 0xbc, 0xc6, 0x20, 0x0b, 0x63, 0x19, 0xb3, 0x78, 0x2c, -0x21, 0x6b, 0x0d, 0xab, 0x86, 0x75, 0x81, 0x35, 0xc4, 0x26, 0xb1, 0xcd, -0xd9, 0x7c, 0x76, 0x2a, 0xbb, 0x98, 0xfd, 0x1d, 0xbb, 0x8b, 0x3d, 0xaa, -0xa9, 0xa1, 0x39, 0x43, 0x33, 0x4a, 0x33, 0x57, 0xb3, 0x52, 0xf3, 0x94, -0x66, 0x3f, 0x07, 0xe3, 0x98, 0x71, 0xf8, 0x9c, 0x74, 0x4e, 0x09, 0xe7, -0x28, 0xa7, 0x97, 0xf3, 0x7e, 0x8a, 0xde, 0x14, 0xef, 0x29, 0xe2, 0x29, -0x1b, 0xa6, 0x34, 0x4c, 0xb9, 0x31, 0x65, 0x5c, 0x6b, 0xaa, 0x96, 0x97, -0x96, 0x58, 0xab, 0x48, 0xab, 0x51, 0xab, 0x47, 0xeb, 0xbd, 0x36, 0xae, -0xed, 0xa7, 0x9d, 0xa6, 0xbd, 0x45, 0xbb, 0x59, 0xfb, 0x81, 0x0e, 0x41, -0xc7, 0x4a, 0x27, 0x5c, 0x27, 0x47, 0x67, 0x8f, 0xce, 0x05, 0x9d, 0xe7, -0x53, 0xd9, 0x53, 0xdd, 0xa7, 0x0a, 0xa7, 0x16, 0x4d, 0x3d, 0x3a, 0xf5, -0xae, 0x2e, 0xaa, 0x6b, 0xa5, 0x1b, 0xa1, 0xbb, 0x44, 0x77, 0xbf, 0x6e, -0xa7, 0xee, 0x98, 0x9e, 0xbe, 0x5e, 0x80, 0x9e, 0x4c, 0x6f, 0xa7, 0xde, -0x79, 0xbd, 0xe7, 0xfa, 0x1c, 0x7d, 0x2f, 0xfd, 0x54, 0xfd, 0x6d, 0xfa, -0xa7, 0xf5, 0x47, 0x0c, 0x58, 0x06, 0xb3, 0x0c, 0x24, 0x06, 0xdb, 0x0c, -0xce, 0x18, 0x3c, 0xc5, 0x35, 0x71, 0x6f, 0x3c, 0x1d, 0x2f, 0xc7, 0xdb, -0xf1, 0x51, 0x43, 0x5d, 0xc3, 0x40, 0x43, 0xa5, 0x61, 0x95, 0x61, 0x97, -0xe1, 0x84, 0x91, 0xb9, 0xd1, 0x3c, 0xa3, 0xd5, 0x46, 0x8d, 0x46, 0x0f, -0x8c, 0x69, 0xc6, 0x5c, 0xe3, 0x24, 0xe3, 0x6d, 0xc6, 0x6d, 0xc6, 0xa3, -0x26, 0x06, 0x26, 0x21, 0x26, 0x4b, 0x4d, 0xea, 0x4d, 0xee, 0x9a, 0x52, -0x4d, 0xb9, 0xa6, 0x29, 0xa6, 0x3b, 0x4c, 0x3b, 0x4c, 0xc7, 0xcd, 0xcc, -0xcd, 0xa2, 0xcd, 0xd6, 0x99, 0x35, 0x9b, 0x3d, 0x31, 0xd7, 0x32, 0xe7, -0x9b, 0xe7, 0x9b, 0xd7, 0x9b, 0xdf, 0xb7, 0x60, 0x5a, 0x78, 0x5a, 0x2c, -0xb6, 0xa8, 0xb6, 0xb8, 0x65, 0x49, 0xb2, 0xe4, 0x5a, 0xa6, 0x59, 0xee, -0xb6, 0xbc, 0x6e, 0x85, 0x5a, 0x39, 0x59, 0xa5, 0x58, 0x55, 0x5a, 0x5d, -0xb3, 0x46, 0xad, 0x9d, 0xad, 0x25, 0xd6, 0xbb, 0xad, 0xbb, 0xa7, 0x11, -0xa7, 0xb9, 0x4e, 0x93, 0x4e, 0xab, 0x9e, 0xd6, 0x67, 0xc3, 0xb0, 0xf1, -0xb6, 0xc9, 0xb6, 0xa9, 0xb7, 0x19, 0xb0, 0xe5, 0xd8, 0x06, 0xdb, 0xae, -0xb6, 0x6d, 0xb6, 0x7d, 0x61, 0x67, 0x62, 0x17, 0x67, 0xb7, 0xc5, 0xae, -0xc3, 0xee, 0x93, 0xbd, 0x93, 0x7d, 0xba, 0x7d, 0x8d, 0xfd, 0x3d, 0x07, -0x0d, 0x87, 0xd9, 0x0e, 0xab, 0x1d, 0x5a, 0x1d, 0x7e, 0x73, 0xb4, 0x72, -0x14, 0x3a, 0x56, 0x3a, 0xde, 0x9a, 0xce, 0x9c, 0xee, 0x3f, 0x7d, 0xc5, -0xf4, 0x96, 0xe9, 0x2f, 0x67, 0x58, 0xcf, 0x10, 0xcf, 0xd8, 0x33, 0xe3, -0xb6, 0x13, 0xcb, 0x29, 0xc4, 0x69, 0x9d, 0x53, 0x9b, 0xd3, 0x47, 0x67, -0x17, 0x67, 0xb9, 0x73, 0x83, 0xf3, 0x88, 0x8b, 0x89, 0x4b, 0x82, 0xcb, -0x2e, 0x97, 0x3e, 0x2e, 0x9b, 0x1b, 0xc6, 0xdd, 0xc8, 0xbd, 0xe4, 0x4a, -0x74, 0xf5, 0x71, 0x5d, 0xe1, 0x7a, 0xd2, 0xf5, 0x9d, 0x9b, 0xb3, 0x9b, -0xc2, 0xed, 0xa8, 0xdb, 0xaf, 0xee, 0x36, 0xee, 0x69, 0xee, 0x87, 0xdc, -0x9f, 0xcc, 0x34, 0x9f, 0x29, 0x9e, 0x59, 0x33, 0x73, 0xd0, 0xc3, 0xc8, -0x43, 0xe0, 0x51, 0xe5, 0xd1, 0x3f, 0x0b, 0x9f, 0x95, 0x30, 0x6b, 0xdf, -0xac, 0x7e, 0x4f, 0x43, 0x4f, 0x81, 0x67, 0xb5, 0xe7, 0x23, 0x2f, 0x63, -0x2f, 0x91, 0x57, 0xad, 0xd7, 0xb0, 0xb7, 0xa5, 0x77, 0xaa, 0xf7, 0x61, -0xef, 0x17, 0x3e, 0xf6, 0x3e, 0x72, 0x9f, 0xe3, 0x3e, 0xe3, 0x3c, 0x37, -0xde, 0x32, 0xde, 0x59, 0x5f, 0xcc, 0x37, 0xc0, 0xb7, 0xc8, 0xb7, 0xcb, -0x4f, 0xc3, 0x6f, 0x9e, 0x5f, 0x85, 0xdf, 0x43, 0x7f, 0x23, 0xff, 0x64, -0xff, 0x7a, 0xff, 0xd1, 0x00, 0xa7, 0x80, 0x25, 0x01, 0x67, 0x03, 0x89, -0x81, 0x41, 0x81, 0x5b, 0x02, 0xfb, 0xf8, 0x7a, 0x7c, 0x21, 0xbf, 0x8e, -0x3f, 0x3a, 0xdb, 0x65, 0xf6, 0xb2, 0xd9, 0xed, 0x41, 0x8c, 0xa0, 0xb9, -0x41, 0x15, 0x41, 0x8f, 0x82, 0xad, 0x82, 0xe5, 0xc1, 0xad, 0x21, 0x68, -0xc8, 0xec, 0x90, 0xad, 0x21, 0xf7, 0xe7, 0x98, 0xce, 0x91, 0xce, 0x69, -0x0e, 0x85, 0x50, 0x7e, 0xe8, 0xd6, 0xd0, 0x07, 0x61, 0xe6, 0x61, 0x8b, -0xc3, 0x7e, 0x0c, 0x27, 0x85, 0x87, 0x85, 0x57, 0x86, 0x3f, 0x8e, 0x70, -0x88, 0x58, 0x1a, 0xd1, 0x31, 0x97, 0x35, 0x77, 0xd1, 0xdc, 0x43, 0x73, -0xdf, 0x44, 0xfa, 0x44, 0x96, 0x44, 0xde, 0x9b, 0x67, 0x31, 0x4f, 0x39, -0xaf, 0x2d, 0x4a, 0x35, 0x2a, 0x3e, 0xaa, 0x2e, 0x6a, 0x3c, 0xda, 0x37, -0xba, 0x34, 0xba, 0x3f, 0xc6, 0x2e, 0x66, 0x59, 0xcc, 0xd5, 0x58, 0x9d, -0x58, 0x49, 0x6c, 0x4b, 0x1c, 0x39, 0x2e, 0x2a, 0xae, 0x36, 0x6e, 0x6c, -0xbe, 0xdf, 0xfc, 0xed, 0xf3, 0x87, 0xe2, 0x9d, 0xe2, 0x0b, 0xe3, 0x7b, -0x17, 0x98, 0x2f, 0xc8, 0x5d, 0x70, 0x79, 0xa1, 0xce, 0xc2, 0xf4, 0x85, -0xa7, 0x16, 0xa9, 0x2e, 0x12, 0x2c, 0x3a, 0x96, 0x40, 0x4c, 0x88, 0x4e, -0x38, 0x94, 0xf0, 0x41, 0x10, 0x2a, 0xa8, 0x16, 0x8c, 0x25, 0xf2, 0x13, -0x77, 0x25, 0x8e, 0x0a, 0x79, 0xc2, 0x1d, 0xc2, 0x67, 0x22, 0x2f, 0xd1, -0x36, 0xd1, 0x88, 0xd8, 0x43, 0x5c, 0x2a, 0x1e, 0x4e, 0xf2, 0x48, 0x2a, -0x4d, 0x7a, 0x92, 0xec, 0x91, 0xbc, 0x35, 0x79, 0x24, 0xc5, 0x33, 0xa5, -0x2c, 0xe5, 0xb9, 0x84, 0x27, 0xa9, 0x90, 0xbc, 0x4c, 0x0d, 0x4c, 0xdd, -0x9b, 0x3a, 0x9e, 0x16, 0x9a, 0x76, 0x20, 0x6d, 0x32, 0x3d, 0x3a, 0xbd, -0x31, 0x83, 0x92, 0x91, 0x90, 0x71, 0x42, 0xaa, 0x21, 0x4d, 0x93, 0xb6, -0x67, 0xea, 0x67, 0xe6, 0x66, 0x76, 0xcb, 0xac, 0x65, 0x85, 0xb2, 0xfe, -0xc5, 0x6e, 0x8b, 0xb7, 0x2f, 0x1e, 0x95, 0x07, 0xc9, 0x6b, 0xb3, 0x90, -0xac, 0x05, 0x59, 0x2d, 0x0a, 0xb6, 0x42, 0xa6, 0xe8, 0x54, 0x5a, 0x28, -0xd7, 0x2a, 0x07, 0xb2, 0x67, 0x65, 0x57, 0x66, 0xbf, 0xcd, 0x89, 0xca, -0x39, 0x96, 0xab, 0x9e, 0x2b, 0xcd, 0xed, 0xcc, 0xb3, 0xca, 0xdb, 0x90, -0x37, 0x9c, 0xef, 0x9f, 0xff, 0xed, 0x12, 0xc2, 0x12, 0xe1, 0x92, 0xb6, -0xa5, 0x86, 0x4b, 0x57, 0x2d, 0x1d, 0x58, 0xe6, 0xbd, 0xac, 0x6a, 0x39, -0xb2, 0x3c, 0x71, 0x79, 0xdb, 0x0a, 0xe3, 0x15, 0x05, 0x2b, 0x86, 0x56, -0x06, 0xac, 0x3c, 0xb8, 0x8a, 0xb6, 0x2a, 0x6d, 0xd5, 0x4f, 0xab, 0xed, -0x57, 0x97, 0xae, 0x7e, 0xbd, 0x26, 0x7a, 0x4d, 0x6b, 0x81, 0x5e, 0xc1, -0xca, 0x82, 0xc1, 0xb5, 0x01, 0x6b, 0xeb, 0x0b, 0x55, 0x0a, 0xe5, 0x85, -0x7d, 0xeb, 0xdc, 0xd7, 0xed, 0x5d, 0x4f, 0x58, 0x2f, 0x59, 0xdf, 0xb5, -0x61, 0xfa, 0x86, 0x9d, 0x1b, 0x3e, 0x15, 0x89, 0x8a, 0xae, 0x14, 0xdb, -0x17, 0x97, 0x15, 0x7f, 0xd8, 0x28, 0xdc, 0x78, 0xe5, 0x1b, 0x87, 0x6f, -0xca, 0xbf, 0x99, 0xdc, 0x94, 0xb4, 0xa9, 0xab, 0xc4, 0xb9, 0x64, 0xcf, -0x66, 0xd2, 0x66, 0xe9, 0xe6, 0xde, 0x2d, 0x9e, 0x5b, 0x0e, 0x96, 0xaa, -0x97, 0xe6, 0x97, 0x0e, 0x6e, 0x0d, 0xd9, 0xda, 0xb4, 0x0d, 0xdf, 0x56, -0xb4, 0xed, 0xf5, 0xf6, 0x45, 0xdb, 0x2f, 0x97, 0xcd, 0x28, 0xdb, 0xbb, -0x83, 0xb6, 0x43, 0xb9, 0xa3, 0xbf, 0x3c, 0xb8, 0xbc, 0x65, 0xa7, 0xc9, -0xce, 0xcd, 0x3b, 0x3f, 0x54, 0xa4, 0x54, 0xf4, 0x54, 0xfa, 0x54, 0x36, -0xee, 0xd2, 0xdd, 0xb5, 0x61, 0xd7, 0xf8, 0x6e, 0xd1, 0xee, 0x1b, 0x7b, -0xbc, 0xf6, 0x34, 0xec, 0xd5, 0xdb, 0x5b, 0xbc, 0xf7, 0xfd, 0x3e, 0xc9, -0xbe, 0xdb, 0x55, 0x01, 0x55, 0x4d, 0xd5, 0x66, 0xd5, 0x65, 0xfb, 0x49, -0xfb, 0xb3, 0xf7, 0x3f, 0xae, 0x89, 0xaa, 0xe9, 0xf8, 0x96, 0xfb, 0x6d, -0x5d, 0xad, 0x4e, 0x6d, 0x71, 0xed, 0xc7, 0x03, 0xd2, 0x03, 0xfd, 0x07, -0x23, 0x0e, 0xb6, 0xd7, 0xb9, 0xd4, 0xd5, 0x1d, 0xd2, 0x3d, 0x54, 0x52, -0x8f, 0xd6, 0x2b, 0xeb, 0x47, 0x0e, 0xc7, 0x1f, 0xbe, 0xfe, 0x9d, 0xef, -0x77, 0x2d, 0x0d, 0x36, 0x0d, 0x55, 0x8d, 0x9c, 0xc6, 0xe2, 0x23, 0x70, -0x44, 0x79, 0xe4, 0xe9, 0xf7, 0x09, 0xdf, 0xf7, 0x1e, 0x0d, 0x3a, 0xda, -0x76, 0x8c, 0x7b, 0xac, 0xe1, 0x07, 0xd3, 0x1f, 0x76, 0x1d, 0x67, 0x1d, -0x2f, 0x6a, 0x42, 0x9a, 0xf2, 0x9a, 0x46, 0x9b, 0x53, 0x9a, 0xfb, 0x5b, -0x62, 0x5b, 0xba, 0x4f, 0xcc, 0x3e, 0xd1, 0xd6, 0xea, 0xde, 0x7a, 0xfc, -0x47, 0xdb, 0x1f, 0x0f, 0x9c, 0x34, 0x3c, 0x59, 0x79, 0x4a, 0xf3, 0x54, -0xc9, 0x69, 0xda, 0xe9, 0x82, 0xd3, 0x93, 0x67, 0xf2, 0xcf, 0x8c, 0x9d, -0x95, 0x9d, 0x7d, 0x7e, 0x2e, 0xf9, 0xdc, 0x60, 0xdb, 0xa2, 0xb6, 0x7b, -0xe7, 0x63, 0xce, 0xdf, 0x6a, 0x0f, 0x6f, 0xef, 0xba, 0x10, 0x74, 0xe1, -0xd2, 0x45, 0xff, 0x8b, 0xe7, 0x3b, 0xbc, 0x3b, 0xce, 0x5c, 0xf2, 0xb8, -0x74, 0xf2, 0xb2, 0xdb, 0xe5, 0x13, 0x57, 0xb8, 0x57, 0x9a, 0xaf, 0x3a, -0x5f, 0x6d, 0xea, 0x74, 0xea, 0x3c, 0xfe, 0x93, 0xd3, 0x4f, 0xc7, 0xbb, -0x9c, 0xbb, 0x9a, 0xae, 0xb9, 0x5c, 0x6b, 0xb9, 0xee, 0x7a, 0xbd, 0xb5, -0x7b, 0x66, 0xf7, 0xe9, 0x1b, 0x9e, 0x37, 0xce, 0xdd, 0xf4, 0xbd, 0x79, -0xf1, 0x16, 0xff, 0xd6, 0xd5, 0x9e, 0x39, 0x3d, 0xdd, 0xbd, 0xf3, 0x7a, -0x6f, 0xf7, 0xc5, 0xf7, 0xf5, 0xdf, 0x16, 0xdd, 0x7e, 0x72, 0x27, 0xfd, -0xce, 0xcb, 0xbb, 0xd9, 0x77, 0x27, 0xee, 0xad, 0xbc, 0x4f, 0xbc, 0x5f, -0xf4, 0x40, 0xed, 0x41, 0xd9, 0x43, 0xdd, 0x87, 0xd5, 0x3f, 0x5b, 0xfe, -0xdc, 0xd8, 0xef, 0xdc, 0x7f, 0x6a, 0xc0, 0x77, 0xa0, 0xf3, 0xd1, 0xdc, -0x47, 0xf7, 0x06, 0x85, 0x83, 0xcf, 0xfe, 0x91, 0xf5, 0x8f, 0x0f, 0x43, -0x05, 0x8f, 0x99, 0x8f, 0xcb, 0x86, 0x0d, 0x86, 0xeb, 0x9e, 0x38, 0x3e, -0x39, 0x39, 0xe2, 0x3f, 0x72, 0xfd, 0xe9, 0xfc, 0xa7, 0x43, 0xcf, 0x64, -0xcf, 0x26, 0x9e, 0x17, 0xfe, 0xa2, 0xfe, 0xcb, 0xae, 0x17, 0x16, 0x2f, -0x7e, 0xf8, 0xd5, 0xeb, 0xd7, 0xce, 0xd1, 0x98, 0xd1, 0xa1, 0x97, 0xf2, -0x97, 0x93, 0xbf, 0x6d, 0x7c, 0xa5, 0xfd, 0xea, 0xc0, 0xeb, 0x19, 0xaf, -0xdb, 0xc6, 0xc2, 0xc6, 0x1e, 0xbe, 0xc9, 0x78, 0x33, 0x31, 0x5e, 0xf4, -0x56, 0xfb, 0xed, 0xc1, 0x77, 0xdc, 0x77, 0x1d, 0xef, 0xa3, 0xdf, 0x0f, -0x4f, 0xe4, 0x7c, 0x20, 0x7f, 0x28, 0xff, 0x68, 0xf9, 0xb1, 0xf5, 0x53, -0xd0, 0xa7, 0xfb, 0x93, 0x19, 0x93, 0x93, 0xff, 0x04, 0x03, 0x98, 0xf3, -0xfc, 0x63, 0x33, 0x2d, 0xdb, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, -0x4d, 0x00, 0x00, 0x7a, 0x25, 0x00, 0x00, 0x80, 0x83, 0x00, 0x00, 0xf9, -0xff, 0x00, 0x00, 0x80, 0xe9, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, -0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00, 0x17, 0x6f, 0x92, 0x5f, 0xc5, -0x46, 0x00, 0x00, 0x02, 0x8c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x4c, -0xcf, 0x4b, 0x6b, 0x13, 0x51, 0x18, 0xc6, 0xf1, 0xf7, 0x72, 0xce, 0xcc, -0x9c, 0x99, 0xc9, 0x4c, 0x12, 0x43, 0x9a, 0x36, 0x58, 0x5b, 0xc5, 0x3b, -0x08, 0x0a, 0xe2, 0xca, 0x9d, 0x60, 0x41, 0xd1, 0x95, 0x75, 0xa3, 0xae, -0x5c, 0xfa, 0x01, 0xfc, 0x0c, 0x22, 0x6e, 0xdc, 0x76, 0xa5, 0x1b, 0x05, -0x11, 0xdc, 0x88, 0x97, 0x8a, 0x20, 0xd5, 0x62, 0x15, 0xbc, 0x94, 0x16, -0xad, 0xd5, 0xd6, 0xd6, 0xd6, 0xb4, 0x35, 0xe9, 0x2d, 0x93, 0xcb, 0x64, -0xce, 0x1c, 0x17, 0x42, 0xed, 0xb3, 0xfe, 0xff, 0x16, 0x0f, 0x3e, 0x79, -0xf9, 0xf6, 0xfb, 0xcc, 0x6c, 0xb9, 0xbb, 0x4b, 0xa7, 0x06, 0x8c, 0x01, -0x00, 0x66, 0x51, 0x8f, 0xa2, 0xd5, 0xd5, 0x55, 0xdf, 0xcf, 0xe4, 0xf2, -0x79, 0x9d, 0xc4, 0x60, 0x0c, 0x13, 0x2e, 0xfc, 0xae, 0xec, 0xd9, 0xdd, -0xcf, 0x5e, 0xb1, 0x7f, 0x57, 0xdf, 0xae, 0x4c, 0x98, 0x37, 0x6c, 0x91, -0xed, 0x49, 0xc7, 0xad, 0xad, 0xd6, 0x28, 0x5e, 0xdf, 0xdb, 0xdf, 0x13, -0x37, 0x37, 0x57, 0x6a, 0x1b, 0xd9, 0x62, 0x19, 0x48, 0xb0, 0x74, 0xe2, -0x4e, 0xfc, 0xe2, 0xd5, 0xa8, 0x20, 0xb7, 0x34, 0x3e, 0xdf, 0xe2, 0xb5, -0xa8, 0xd1, 0x6c, 0x60, 0xb4, 0x94, 0xd8, 0xc1, 0xb1, 0x1d, 0x8d, 0xcb, -0x97, 0x2e, 0xb0, 0x90, 0x00, 0xf0, 0xe4, 0xe9, 0xf3, 0x87, 0x23, 0x9f, -0xc3, 0x62, 0x1f, 0xe8, 0xa4, 0xbd, 0xd1, 0x64, 0xb7, 0x4c, 0x1b, 0x71, -0x76, 0x64, 0x5a, 0x4f, 0xcf, 0xcf, 0x43, 0xe5, 0xc3, 0xd1, 0x1e, 0x5e, -0x1c, 0x1f, 0xb9, 0x32, 0x78, 0xfe, 0x5f, 0x0d, 0x00, 0x03, 0xa7, 0x4f, -0x31, 0x25, 0x6f, 0x16, 0xf4, 0xfb, 0xc5, 0xce, 0xdb, 0x1f, 0xa6, 0xae, -0x0b, 0xa2, 0x99, 0x78, 0x93, 0x7f, 0x30, 0x15, 0xcb, 0xb7, 0xae, 0x9d, -0x2b, 0x74, 0x97, 0x43, 0x57, 0x4a, 0xcb, 0x86, 0xff, 0xc3, 0xbe, 0x82, -0x7f, 0xef, 0x43, 0xd3, 0x57, 0x99, 0xcd, 0x6a, 0xb2, 0x33, 0x60, 0x02, -0x69, 0x27, 0xaa, 0x6b, 0x2e, 0x0d, 0x1a, 0x71, 0x27, 0x08, 0xc2, 0x0b, -0x83, 0x83, 0xcc, 0xbc, 0x0d, 0xc0, 0xc9, 0x83, 0x65, 0x76, 0x6c, 0x93, -0x2b, 0x45, 0x9c, 0xd3, 0x40, 0x24, 0x7c, 0xe1, 0x15, 0x03, 0xd9, 0xd3, -0xf7, 0x60, 0x74, 0x6a, 0x71, 0xf6, 0x3b, 0x00, 0x20, 0xe2, 0x56, 0x3d, -0x31, 0x39, 0x79, 0xfd, 0xd9, 0x5c, 0x76, 0xef, 0x21, 0x2f, 0x50, 0x7e, -0xa9, 0xc0, 0xae, 0x45, 0x68, 0x83, 0x50, 0x3a, 0xdf, 0x5d, 0xba, 0xd3, -0x38, 0x38, 0x30, 0xf4, 0xf9, 0xe6, 0xdd, 0x47, 0x9d, 0x56, 0x73, 0x0b, -0x30, 0x0b, 0x4b, 0x90, 0xb0, 0x12, 0x92, 0x1a, 0x44, 0x9b, 0xec, 0x94, -0x10, 0x53, 0xa9, 0x50, 0x71, 0x92, 0x2b, 0x14, 0xf4, 0xfe, 0x93, 0xb7, -0x7f, 0xb8, 0x9f, 0x26, 0xbe, 0x6e, 0x81, 0x03, 0xfb, 0xf7, 0x3d, 0xbc, -0x7a, 0xa2, 0xab, 0xf2, 0x0e, 0x6c, 0x96, 0x0a, 0x49, 0x80, 0x80, 0x54, -0x2b, 0x65, 0xd9, 0x16, 0x03, 0x1a, 0x1b, 0x53, 0xc7, 0x53, 0x92, 0x68, -0xfb, 0x87, 0xd9, 0xea, 0x26, 0xa8, 0x4c, 0xe8, 0xda, 0xad, 0x8c, 0x62, -0x89, 0x84, 0x88, 0xc8, 0x64, 0x8c, 0x31, 0x3a, 0x61, 0x00, 0xad, 0x32, -0x2b, 0xcd, 0x78, 0x3b, 0x18, 0x7a, 0xfd, 0x6d, 0xa3, 0x78, 0x88, 0x75, -0x02, 0x44, 0x48, 0x4c, 0x44, 0xc0, 0xa0, 0x2d, 0x41, 0x96, 0x60, 0xc7, -0x22, 0xb2, 0xad, 0xf5, 0x56, 0x07, 0x00, 0xa2, 0x28, 0x8a, 0xe3, 0xb8, -0x5e, 0x5b, 0xf9, 0xd9, 0x14, 0xb9, 0xc0, 0x27, 0x48, 0x6d, 0x5b, 0x90, -0x60, 0x12, 0x8c, 0x59, 0x4f, 0x64, 0x7d, 0x99, 0x51, 0xe4, 0xda, 0xe8, -0xb6, 0xab, 0xbd, 0xa1, 0x03, 0x00, 0xc3, 0xc3, 0xc3, 0x95, 0x4a, 0xa5, -0x95, 0x68, 0x8e, 0xd7, 0x5c, 0x53, 0x0f, 0x3d, 0x11, 0xba, 0x88, 0xba, -0x43, 0x42, 0x70, 0xce, 0x25, 0x8f, 0x75, 0xa8, 0x84, 0xab, 0xa3, 0xb3, -0x99, 0x95, 0xe3, 0xc7, 0x8e, 0x00, 0xc0, 0xe2, 0xaf, 0x39, 0x47, 0x72, -0xa1, 0x58, 0xba, 0x71, 0xe6, 0x70, 0x50, 0x9d, 0x2a, 0xe4, 0xbc, 0xbc, -0x02, 0x46, 0x23, 0x74, 0xa7, 0x2d, 0x09, 0x9d, 0xd4, 0x20, 0x52, 0x42, -0xc2, 0x41, 0x1c, 0x1d, 0xfb, 0x38, 0x53, 0xa9, 0x8e, 0xad, 0x79, 0x33, -0x8f, 0x3f, 0xed, 0x70, 0xc6, 0xd7, 0x3b, 0xc6, 0xef, 0x3e, 0x22, 0x8c, -0xb6, 0x19, 0xd3, 0xb8, 0x85, 0x4f, 0x47, 0xbf, 0xdc, 0x1f, 0xfb, 0x65, -0x79, 0x1e, 0x9a, 0x94, 0xa4, 0x5c, 0x5f, 0x5a, 0xae, 0xd7, 0xaa, 0x42, -0x79, 0xd9, 0x52, 0x19, 0x00, 0x52, 0x48, 0x85, 0x64, 0x4b, 0x90, 0x8e, -0xe3, 0x76, 0x54, 0xbf, 0x78, 0xa2, 0xf7, 0xef, 0x00, 0x3c, 0x80, 0x08, -0x61, 0x0e, 0x41, 0xd5, 0x83, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, -0x44, 0xae, 0x42, 0x60, 0x82, +static const unsigned char dolphin_ico32x32[] = { +0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, +0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, +0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x73, +0x7A, 0x7A, 0xF4, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, +0x73, 0x00, 0x00, 0x0B, 0x13, 0x00, 0x00, 0x0B, 0x13, 0x01, +0x00, 0x9A, 0x9C, 0x18, 0x00, 0x00, 0x0A, 0x4F, 0x69, 0x43, +0x43, 0x50, 0x50, 0x68, 0x6F, 0x74, 0x6F, 0x73, 0x68, 0x6F, +0x70, 0x20, 0x49, 0x43, 0x43, 0x20, 0x70, 0x72, 0x6F, 0x66, +0x69, 0x6C, 0x65, 0x00, 0x00, 0x78, 0xDA, 0x9D, 0x53, 0x67, +0x54, 0x53, 0xE9, 0x16, 0x3D, 0xF7, 0xDE, 0xF4, 0x42, 0x4B, +0x88, 0x80, 0x94, 0x4B, 0x6F, 0x52, 0x15, 0x08, 0x20, 0x52, +0x42, 0x8B, 0x80, 0x14, 0x91, 0x26, 0x2A, 0x21, 0x09, 0x10, +0x4A, 0x88, 0x21, 0xA1, 0xD9, 0x15, 0x51, 0xC1, 0x11, 0x45, +0x45, 0x04, 0x1B, 0xC8, 0xA0, 0x88, 0x03, 0x8E, 0x8E, 0x80, +0x8C, 0x15, 0x51, 0x2C, 0x0C, 0x8A, 0x0A, 0xD8, 0x07, 0xE4, +0x21, 0xA2, 0x8E, 0x83, 0xA3, 0x88, 0x8A, 0xCA, 0xFB, 0xE1, +0x7B, 0xA3, 0x6B, 0xD6, 0xBC, 0xF7, 0xE6, 0xCD, 0xFE, 0xB5, +0xD7, 0x3E, 0xE7, 0xAC, 0xF3, 0x9D, 0xB3, 0xCF, 0x07, 0xC0, +0x08, 0x0C, 0x96, 0x48, 0x33, 0x51, 0x35, 0x80, 0x0C, 0xA9, +0x42, 0x1E, 0x11, 0xE0, 0x83, 0xC7, 0xC4, 0xC6, 0xE1, 0xE4, +0x2E, 0x40, 0x81, 0x0A, 0x24, 0x70, 0x00, 0x10, 0x08, 0xB3, +0x64, 0x21, 0x73, 0xFD, 0x23, 0x01, 0x00, 0xF8, 0x7E, 0x3C, +0x3C, 0x2B, 0x22, 0xC0, 0x07, 0xBE, 0x00, 0x01, 0x78, 0xD3, +0x0B, 0x08, 0x00, 0xC0, 0x4D, 0x9B, 0xC0, 0x30, 0x1C, 0x87, +0xFF, 0x0F, 0xEA, 0x42, 0x99, 0x5C, 0x01, 0x80, 0x84, 0x01, +0xC0, 0x74, 0x91, 0x38, 0x4B, 0x08, 0x80, 0x14, 0x00, 0x40, +0x7A, 0x8E, 0x42, 0xA6, 0x00, 0x40, 0x46, 0x01, 0x80, 0x9D, +0x98, 0x26, 0x53, 0x00, 0xA0, 0x04, 0x00, 0x60, 0xCB, 0x63, +0x62, 0xE3, 0x00, 0x50, 0x2D, 0x00, 0x60, 0x27, 0x7F, 0xE6, +0xD3, 0x00, 0x80, 0x9D, 0xF8, 0x99, 0x7B, 0x01, 0x00, 0x5B, +0x94, 0x21, 0x15, 0x01, 0xA0, 0x91, 0x00, 0x20, 0x13, 0x65, +0x88, 0x44, 0x00, 0x68, 0x3B, 0x00, 0xAC, 0xCF, 0x56, 0x8A, +0x45, 0x00, 0x58, 0x30, 0x00, 0x14, 0x66, 0x4B, 0xC4, 0x39, +0x00, 0xD8, 0x2D, 0x00, 0x30, 0x49, 0x57, 0x66, 0x48, 0x00, +0xB0, 0xB7, 0x00, 0xC0, 0xCE, 0x10, 0x0B, 0xB2, 0x00, 0x08, +0x0C, 0x00, 0x30, 0x51, 0x88, 0x85, 0x29, 0x00, 0x04, 0x7B, +0x00, 0x60, 0xC8, 0x23, 0x23, 0x78, 0x00, 0x84, 0x99, 0x00, +0x14, 0x46, 0xF2, 0x57, 0x3C, 0xF1, 0x2B, 0xAE, 0x10, 0xE7, +0x2A, 0x00, 0x00, 0x78, 0x99, 0xB2, 0x3C, 0xB9, 0x24, 0x39, +0x45, 0x81, 0x5B, 0x08, 0x2D, 0x71, 0x07, 0x57, 0x57, 0x2E, +0x1E, 0x28, 0xCE, 0x49, 0x17, 0x2B, 0x14, 0x36, 0x61, 0x02, +0x61, 0x9A, 0x40, 0x2E, 0xC2, 0x79, 0x99, 0x19, 0x32, 0x81, +0x34, 0x0F, 0xE0, 0xF3, 0xCC, 0x00, 0x00, 0xA0, 0x91, 0x15, +0x11, 0xE0, 0x83, 0xF3, 0xFD, 0x78, 0xCE, 0x0E, 0xAE, 0xCE, +0xCE, 0x36, 0x8E, 0xB6, 0x0E, 0x5F, 0x2D, 0xEA, 0xBF, 0x06, +0xFF, 0x22, 0x62, 0x62, 0xE3, 0xFE, 0xE5, 0xCF, 0xAB, 0x70, +0x40, 0x00, 0x00, 0xE1, 0x74, 0x7E, 0xD1, 0xFE, 0x2C, 0x2F, +0xB3, 0x1A, 0x80, 0x3B, 0x06, 0x80, 0x6D, 0xFE, 0xA2, 0x25, +0xEE, 0x04, 0x68, 0x5E, 0x0B, 0xA0, 0x75, 0xF7, 0x8B, 0x66, +0xB2, 0x0F, 0x40, 0xB5, 0x00, 0xA0, 0xE9, 0xDA, 0x57, 0xF3, +0x70, 0xF8, 0x7E, 0x3C, 0x3C, 0x45, 0xA1, 0x90, 0xB9, 0xD9, +0xD9, 0xE5, 0xE4, 0xE4, 0xD8, 0x4A, 0xC4, 0x42, 0x5B, 0x61, +0xCA, 0x57, 0x7D, 0xFE, 0x67, 0xC2, 0x5F, 0xC0, 0x57, 0xFD, +0x6C, 0xF9, 0x7E, 0x3C, 0xFC, 0xF7, 0xF5, 0xE0, 0xBE, 0xE2, +0x24, 0x81, 0x32, 0x5D, 0x81, 0x47, 0x04, 0xF8, 0xE0, 0xC2, +0xCC, 0xF4, 0x4C, 0xA5, 0x1C, 0xCF, 0x92, 0x09, 0x84, 0x62, +0xDC, 0xE6, 0x8F, 0x47, 0xFC, 0xB7, 0x0B, 0xFF, 0xFC, 0x1D, +0xD3, 0x22, 0xC4, 0x49, 0x62, 0xB9, 0x58, 0x2A, 0x14, 0xE3, +0x51, 0x12, 0x71, 0x8E, 0x44, 0x9A, 0x8C, 0xF3, 0x32, 0xA5, +0x22, 0x89, 0x42, 0x92, 0x29, 0xC5, 0x25, 0xD2, 0xFF, 0x64, +0xE2, 0xDF, 0x2C, 0xFB, 0x03, 0x3E, 0xDF, 0x35, 0x00, 0xB0, +0x6A, 0x3E, 0x01, 0x7B, 0x91, 0x2D, 0xA8, 0x5D, 0x63, 0x03, +0xF6, 0x4B, 0x27, 0x10, 0x58, 0x74, 0xC0, 0xE2, 0xF7, 0x00, +0x00, 0xF2, 0xBB, 0x6F, 0xC1, 0xD4, 0x28, 0x08, 0x03, 0x80, +0x68, 0x83, 0xE1, 0xCF, 0x77, 0xFF, 0xEF, 0x3F, 0xFD, 0x47, +0xA0, 0x25, 0x00, 0x80, 0x66, 0x49, 0x92, 0x71, 0x00, 0x00, +0x5E, 0x44, 0x24, 0x2E, 0x54, 0xCA, 0xB3, 0x3F, 0xC7, 0x08, +0x00, 0x00, 0x44, 0xA0, 0x81, 0x2A, 0xB0, 0x41, 0x1B, 0xF4, +0xC1, 0x18, 0x2C, 0xC0, 0x06, 0x1C, 0xC1, 0x05, 0xDC, 0xC1, +0x0B, 0xFC, 0x60, 0x36, 0x84, 0x42, 0x24, 0xC4, 0xC2, 0x42, +0x10, 0x42, 0x0A, 0x64, 0x80, 0x1C, 0x72, 0x60, 0x29, 0xAC, +0x82, 0x42, 0x28, 0x86, 0xCD, 0xB0, 0x1D, 0x2A, 0x60, 0x2F, +0xD4, 0x40, 0x1D, 0x34, 0xC0, 0x51, 0x68, 0x86, 0x93, 0x70, +0x0E, 0x2E, 0xC2, 0x55, 0xB8, 0x0E, 0x3D, 0x70, 0x0F, 0xFA, +0x61, 0x08, 0x9E, 0xC1, 0x28, 0xBC, 0x81, 0x09, 0x04, 0x41, +0xC8, 0x08, 0x13, 0x61, 0x21, 0xDA, 0x88, 0x01, 0x62, 0x8A, +0x58, 0x23, 0x8E, 0x08, 0x17, 0x99, 0x85, 0xF8, 0x21, 0xC1, +0x48, 0x04, 0x12, 0x8B, 0x24, 0x20, 0xC9, 0x88, 0x14, 0x51, +0x22, 0x4B, 0x91, 0x35, 0x48, 0x31, 0x52, 0x8A, 0x54, 0x20, +0x55, 0x48, 0x1D, 0xF2, 0x3D, 0x72, 0x02, 0x39, 0x87, 0x5C, +0x46, 0xBA, 0x91, 0x3B, 0xC8, 0x00, 0x32, 0x82, 0xFC, 0x86, +0xBC, 0x47, 0x31, 0x94, 0x81, 0xB2, 0x51, 0x3D, 0xD4, 0x0C, +0xB5, 0x43, 0xB9, 0xA8, 0x37, 0x1A, 0x84, 0x46, 0xA2, 0x0B, +0xD0, 0x64, 0x74, 0x31, 0x9A, 0x8F, 0x16, 0xA0, 0x9B, 0xD0, +0x72, 0xB4, 0x1A, 0x3D, 0x8C, 0x36, 0xA1, 0xE7, 0xD0, 0xAB, +0x68, 0x0F, 0xDA, 0x8F, 0x3E, 0x43, 0xC7, 0x30, 0xC0, 0xE8, +0x18, 0x07, 0x33, 0xC4, 0x6C, 0x30, 0x2E, 0xC6, 0xC3, 0x42, +0xB1, 0x38, 0x2C, 0x09, 0x93, 0x63, 0xCB, 0xB1, 0x22, 0xAC, +0x0C, 0xAB, 0xC6, 0x1A, 0xB0, 0x56, 0xAC, 0x03, 0xBB, 0x89, +0xF5, 0x63, 0xCF, 0xB1, 0x77, 0x04, 0x12, 0x81, 0x45, 0xC0, +0x09, 0x36, 0x04, 0x77, 0x42, 0x20, 0x61, 0x1E, 0x41, 0x48, +0x58, 0x4C, 0x58, 0x4E, 0xD8, 0x48, 0xA8, 0x20, 0x1C, 0x24, +0x34, 0x11, 0xDA, 0x09, 0x37, 0x09, 0x03, 0x84, 0x51, 0xC2, +0x27, 0x22, 0x93, 0xA8, 0x4B, 0xB4, 0x26, 0xBA, 0x11, 0xF9, +0xC4, 0x18, 0x62, 0x32, 0x31, 0x87, 0x58, 0x48, 0x2C, 0x23, +0xD6, 0x12, 0x8F, 0x13, 0x2F, 0x10, 0x7B, 0x88, 0x43, 0xC4, +0x37, 0x24, 0x12, 0x89, 0x43, 0x32, 0x27, 0xB9, 0x90, 0x02, +0x49, 0xB1, 0xA4, 0x54, 0xD2, 0x12, 0xD2, 0x46, 0xD2, 0x6E, +0x52, 0x23, 0xE9, 0x2C, 0xA9, 0x9B, 0x34, 0x48, 0x1A, 0x23, +0x93, 0xC9, 0xDA, 0x64, 0x6B, 0xB2, 0x07, 0x39, 0x94, 0x2C, +0x20, 0x2B, 0xC8, 0x85, 0xE4, 0x9D, 0xE4, 0xC3, 0xE4, 0x33, +0xE4, 0x1B, 0xE4, 0x21, 0xF2, 0x5B, 0x0A, 0x9D, 0x62, 0x40, +0x71, 0xA4, 0xF8, 0x53, 0xE2, 0x28, 0x52, 0xCA, 0x6A, 0x4A, +0x19, 0xE5, 0x10, 0xE5, 0x34, 0xE5, 0x06, 0x65, 0x98, 0x32, +0x41, 0x55, 0xA3, 0x9A, 0x52, 0xDD, 0xA8, 0xA1, 0x54, 0x11, +0x35, 0x8F, 0x5A, 0x42, 0xAD, 0xA1, 0xB6, 0x52, 0xAF, 0x51, +0x87, 0xA8, 0x13, 0x34, 0x75, 0x9A, 0x39, 0xCD, 0x83, 0x16, +0x49, 0x4B, 0xA5, 0xAD, 0xA2, 0x95, 0xD3, 0x1A, 0x68, 0x17, +0x68, 0xF7, 0x69, 0xAF, 0xE8, 0x74, 0xBA, 0x11, 0xDD, 0x95, +0x1E, 0x4E, 0x97, 0xD0, 0x57, 0xD2, 0xCB, 0xE9, 0x47, 0xE8, +0x97, 0xE8, 0x03, 0xF4, 0x77, 0x0C, 0x0D, 0x86, 0x15, 0x83, +0xC7, 0x88, 0x67, 0x28, 0x19, 0x9B, 0x18, 0x07, 0x18, 0x67, +0x19, 0x77, 0x18, 0xAF, 0x98, 0x4C, 0xA6, 0x19, 0xD3, 0x8B, +0x19, 0xC7, 0x54, 0x30, 0x37, 0x31, 0xEB, 0x98, 0xE7, 0x99, +0x0F, 0x99, 0x6F, 0x55, 0x58, 0x2A, 0xB6, 0x2A, 0x7C, 0x15, +0x91, 0xCA, 0x0A, 0x95, 0x4A, 0x95, 0x26, 0x95, 0x1B, 0x2A, +0x2F, 0x54, 0xA9, 0xAA, 0xA6, 0xAA, 0xDE, 0xAA, 0x0B, 0x55, +0xF3, 0x55, 0xCB, 0x54, 0x8F, 0xA9, 0x5E, 0x53, 0x7D, 0xAE, +0x46, 0x55, 0x33, 0x53, 0xE3, 0xA9, 0x09, 0xD4, 0x96, 0xAB, +0x55, 0xAA, 0x9D, 0x50, 0xEB, 0x53, 0x1B, 0x53, 0x67, 0xA9, +0x3B, 0xA8, 0x87, 0xAA, 0x67, 0xA8, 0x6F, 0x54, 0x3F, 0xA4, +0x7E, 0x59, 0xFD, 0x89, 0x06, 0x59, 0xC3, 0x4C, 0xC3, 0x4F, +0x43, 0xA4, 0x51, 0xA0, 0xB1, 0x5F, 0xE3, 0xBC, 0xC6, 0x20, +0x0B, 0x63, 0x19, 0xB3, 0x78, 0x2C, 0x21, 0x6B, 0x0D, 0xAB, +0x86, 0x75, 0x81, 0x35, 0xC4, 0x26, 0xB1, 0xCD, 0xD9, 0x7C, +0x76, 0x2A, 0xBB, 0x98, 0xFD, 0x1D, 0xBB, 0x8B, 0x3D, 0xAA, +0xA9, 0xA1, 0x39, 0x43, 0x33, 0x4A, 0x33, 0x57, 0xB3, 0x52, +0xF3, 0x94, 0x66, 0x3F, 0x07, 0xE3, 0x98, 0x71, 0xF8, 0x9C, +0x74, 0x4E, 0x09, 0xE7, 0x28, 0xA7, 0x97, 0xF3, 0x7E, 0x8A, +0xDE, 0x14, 0xEF, 0x29, 0xE2, 0x29, 0x1B, 0xA6, 0x34, 0x4C, +0xB9, 0x31, 0x65, 0x5C, 0x6B, 0xAA, 0x96, 0x97, 0x96, 0x58, +0xAB, 0x48, 0xAB, 0x51, 0xAB, 0x47, 0xEB, 0xBD, 0x36, 0xAE, +0xED, 0xA7, 0x9D, 0xA6, 0xBD, 0x45, 0xBB, 0x59, 0xFB, 0x81, +0x0E, 0x41, 0xC7, 0x4A, 0x27, 0x5C, 0x27, 0x47, 0x67, 0x8F, +0xCE, 0x05, 0x9D, 0xE7, 0x53, 0xD9, 0x53, 0xDD, 0xA7, 0x0A, +0xA7, 0x16, 0x4D, 0x3D, 0x3A, 0xF5, 0xAE, 0x2E, 0xAA, 0x6B, +0xA5, 0x1B, 0xA1, 0xBB, 0x44, 0x77, 0xBF, 0x6E, 0xA7, 0xEE, +0x98, 0x9E, 0xBE, 0x5E, 0x80, 0x9E, 0x4C, 0x6F, 0xA7, 0xDE, +0x79, 0xBD, 0xE7, 0xFA, 0x1C, 0x7D, 0x2F, 0xFD, 0x54, 0xFD, +0x6D, 0xFA, 0xA7, 0xF5, 0x47, 0x0C, 0x58, 0x06, 0xB3, 0x0C, +0x24, 0x06, 0xDB, 0x0C, 0xCE, 0x18, 0x3C, 0xC5, 0x35, 0x71, +0x6F, 0x3C, 0x1D, 0x2F, 0xC7, 0xDB, 0xF1, 0x51, 0x43, 0x5D, +0xC3, 0x40, 0x43, 0xA5, 0x61, 0x95, 0x61, 0x97, 0xE1, 0x84, +0x91, 0xB9, 0xD1, 0x3C, 0xA3, 0xD5, 0x46, 0x8D, 0x46, 0x0F, +0x8C, 0x69, 0xC6, 0x5C, 0xE3, 0x24, 0xE3, 0x6D, 0xC6, 0x6D, +0xC6, 0xA3, 0x26, 0x06, 0x26, 0x21, 0x26, 0x4B, 0x4D, 0xEA, +0x4D, 0xEE, 0x9A, 0x52, 0x4D, 0xB9, 0xA6, 0x29, 0xA6, 0x3B, +0x4C, 0x3B, 0x4C, 0xC7, 0xCD, 0xCC, 0xCD, 0xA2, 0xCD, 0xD6, +0x99, 0x35, 0x9B, 0x3D, 0x31, 0xD7, 0x32, 0xE7, 0x9B, 0xE7, +0x9B, 0xD7, 0x9B, 0xDF, 0xB7, 0x60, 0x5A, 0x78, 0x5A, 0x2C, +0xB6, 0xA8, 0xB6, 0xB8, 0x65, 0x49, 0xB2, 0xE4, 0x5A, 0xA6, +0x59, 0xEE, 0xB6, 0xBC, 0x6E, 0x85, 0x5A, 0x39, 0x59, 0xA5, +0x58, 0x55, 0x5A, 0x5D, 0xB3, 0x46, 0xAD, 0x9D, 0xAD, 0x25, +0xD6, 0xBB, 0xAD, 0xBB, 0xA7, 0x11, 0xA7, 0xB9, 0x4E, 0x93, +0x4E, 0xAB, 0x9E, 0xD6, 0x67, 0xC3, 0xB0, 0xF1, 0xB6, 0xC9, +0xB6, 0xA9, 0xB7, 0x19, 0xB0, 0xE5, 0xD8, 0x06, 0xDB, 0xAE, +0xB6, 0x6D, 0xB6, 0x7D, 0x61, 0x67, 0x62, 0x17, 0x67, 0xB7, +0xC5, 0xAE, 0xC3, 0xEE, 0x93, 0xBD, 0x93, 0x7D, 0xBA, 0x7D, +0x8D, 0xFD, 0x3D, 0x07, 0x0D, 0x87, 0xD9, 0x0E, 0xAB, 0x1D, +0x5A, 0x1D, 0x7E, 0x73, 0xB4, 0x72, 0x14, 0x3A, 0x56, 0x3A, +0xDE, 0x9A, 0xCE, 0x9C, 0xEE, 0x3F, 0x7D, 0xC5, 0xF4, 0x96, +0xE9, 0x2F, 0x67, 0x58, 0xCF, 0x10, 0xCF, 0xD8, 0x33, 0xE3, +0xB6, 0x13, 0xCB, 0x29, 0xC4, 0x69, 0x9D, 0x53, 0x9B, 0xD3, +0x47, 0x67, 0x17, 0x67, 0xB9, 0x73, 0x83, 0xF3, 0x88, 0x8B, +0x89, 0x4B, 0x82, 0xCB, 0x2E, 0x97, 0x3E, 0x2E, 0x9B, 0x1B, +0xC6, 0xDD, 0xC8, 0xBD, 0xE4, 0x4A, 0x74, 0xF5, 0x71, 0x5D, +0xE1, 0x7A, 0xD2, 0xF5, 0x9D, 0x9B, 0xB3, 0x9B, 0xC2, 0xED, +0xA8, 0xDB, 0xAF, 0xEE, 0x36, 0xEE, 0x69, 0xEE, 0x87, 0xDC, +0x9F, 0xCC, 0x34, 0x9F, 0x29, 0x9E, 0x59, 0x33, 0x73, 0xD0, +0xC3, 0xC8, 0x43, 0xE0, 0x51, 0xE5, 0xD1, 0x3F, 0x0B, 0x9F, +0x95, 0x30, 0x6B, 0xDF, 0xAC, 0x7E, 0x4F, 0x43, 0x4F, 0x81, +0x67, 0xB5, 0xE7, 0x23, 0x2F, 0x63, 0x2F, 0x91, 0x57, 0xAD, +0xD7, 0xB0, 0xB7, 0xA5, 0x77, 0xAA, 0xF7, 0x61, 0xEF, 0x17, +0x3E, 0xF6, 0x3E, 0x72, 0x9F, 0xE3, 0x3E, 0xE3, 0x3C, 0x37, +0xDE, 0x32, 0xDE, 0x59, 0x5F, 0xCC, 0x37, 0xC0, 0xB7, 0xC8, +0xB7, 0xCB, 0x4F, 0xC3, 0x6F, 0x9E, 0x5F, 0x85, 0xDF, 0x43, +0x7F, 0x23, 0xFF, 0x64, 0xFF, 0x7A, 0xFF, 0xD1, 0x00, 0xA7, +0x80, 0x25, 0x01, 0x67, 0x03, 0x89, 0x81, 0x41, 0x81, 0x5B, +0x02, 0xFB, 0xF8, 0x7A, 0x7C, 0x21, 0xBF, 0x8E, 0x3F, 0x3A, +0xDB, 0x65, 0xF6, 0xB2, 0xD9, 0xED, 0x41, 0x8C, 0xA0, 0xB9, +0x41, 0x15, 0x41, 0x8F, 0x82, 0xAD, 0x82, 0xE5, 0xC1, 0xAD, +0x21, 0x68, 0xC8, 0xEC, 0x90, 0xAD, 0x21, 0xF7, 0xE7, 0x98, +0xCE, 0x91, 0xCE, 0x69, 0x0E, 0x85, 0x50, 0x7E, 0xE8, 0xD6, +0xD0, 0x07, 0x61, 0xE6, 0x61, 0x8B, 0xC3, 0x7E, 0x0C, 0x27, +0x85, 0x87, 0x85, 0x57, 0x86, 0x3F, 0x8E, 0x70, 0x88, 0x58, +0x1A, 0xD1, 0x31, 0x97, 0x35, 0x77, 0xD1, 0xDC, 0x43, 0x73, +0xDF, 0x44, 0xFA, 0x44, 0x96, 0x44, 0xDE, 0x9B, 0x67, 0x31, +0x4F, 0x39, 0xAF, 0x2D, 0x4A, 0x35, 0x2A, 0x3E, 0xAA, 0x2E, +0x6A, 0x3C, 0xDA, 0x37, 0xBA, 0x34, 0xBA, 0x3F, 0xC6, 0x2E, +0x66, 0x59, 0xCC, 0xD5, 0x58, 0x9D, 0x58, 0x49, 0x6C, 0x4B, +0x1C, 0x39, 0x2E, 0x2A, 0xAE, 0x36, 0x6E, 0x6C, 0xBE, 0xDF, +0xFC, 0xED, 0xF3, 0x87, 0xE2, 0x9D, 0xE2, 0x0B, 0xE3, 0x7B, +0x17, 0x98, 0x2F, 0xC8, 0x5D, 0x70, 0x79, 0xA1, 0xCE, 0xC2, +0xF4, 0x85, 0xA7, 0x16, 0xA9, 0x2E, 0x12, 0x2C, 0x3A, 0x96, +0x40, 0x4C, 0x88, 0x4E, 0x38, 0x94, 0xF0, 0x41, 0x10, 0x2A, +0xA8, 0x16, 0x8C, 0x25, 0xF2, 0x13, 0x77, 0x25, 0x8E, 0x0A, +0x79, 0xC2, 0x1D, 0xC2, 0x67, 0x22, 0x2F, 0xD1, 0x36, 0xD1, +0x88, 0xD8, 0x43, 0x5C, 0x2A, 0x1E, 0x4E, 0xF2, 0x48, 0x2A, +0x4D, 0x7A, 0x92, 0xEC, 0x91, 0xBC, 0x35, 0x79, 0x24, 0xC5, +0x33, 0xA5, 0x2C, 0xE5, 0xB9, 0x84, 0x27, 0xA9, 0x90, 0xBC, +0x4C, 0x0D, 0x4C, 0xDD, 0x9B, 0x3A, 0x9E, 0x16, 0x9A, 0x76, +0x20, 0x6D, 0x32, 0x3D, 0x3A, 0xBD, 0x31, 0x83, 0x92, 0x91, +0x90, 0x71, 0x42, 0xAA, 0x21, 0x4D, 0x93, 0xB6, 0x67, 0xEA, +0x67, 0xE6, 0x66, 0x76, 0xCB, 0xAC, 0x65, 0x85, 0xB2, 0xFE, +0xC5, 0x6E, 0x8B, 0xB7, 0x2F, 0x1E, 0x95, 0x07, 0xC9, 0x6B, +0xB3, 0x90, 0xAC, 0x05, 0x59, 0x2D, 0x0A, 0xB6, 0x42, 0xA6, +0xE8, 0x54, 0x5A, 0x28, 0xD7, 0x2A, 0x07, 0xB2, 0x67, 0x65, +0x57, 0x66, 0xBF, 0xCD, 0x89, 0xCA, 0x39, 0x96, 0xAB, 0x9E, +0x2B, 0xCD, 0xED, 0xCC, 0xB3, 0xCA, 0xDB, 0x90, 0x37, 0x9C, +0xEF, 0x9F, 0xFF, 0xED, 0x12, 0xC2, 0x12, 0xE1, 0x92, 0xB6, +0xA5, 0x86, 0x4B, 0x57, 0x2D, 0x1D, 0x58, 0xE6, 0xBD, 0xAC, +0x6A, 0x39, 0xB2, 0x3C, 0x71, 0x79, 0xDB, 0x0A, 0xE3, 0x15, +0x05, 0x2B, 0x86, 0x56, 0x06, 0xAC, 0x3C, 0xB8, 0x8A, 0xB6, +0x2A, 0x6D, 0xD5, 0x4F, 0xAB, 0xED, 0x57, 0x97, 0xAE, 0x7E, +0xBD, 0x26, 0x7A, 0x4D, 0x6B, 0x81, 0x5E, 0xC1, 0xCA, 0x82, +0xC1, 0xB5, 0x01, 0x6B, 0xEB, 0x0B, 0x55, 0x0A, 0xE5, 0x85, +0x7D, 0xEB, 0xDC, 0xD7, 0xED, 0x5D, 0x4F, 0x58, 0x2F, 0x59, +0xDF, 0xB5, 0x61, 0xFA, 0x86, 0x9D, 0x1B, 0x3E, 0x15, 0x89, +0x8A, 0xAE, 0x14, 0xDB, 0x17, 0x97, 0x15, 0x7F, 0xD8, 0x28, +0xDC, 0x78, 0xE5, 0x1B, 0x87, 0x6F, 0xCA, 0xBF, 0x99, 0xDC, +0x94, 0xB4, 0xA9, 0xAB, 0xC4, 0xB9, 0x64, 0xCF, 0x66, 0xD2, +0x66, 0xE9, 0xE6, 0xDE, 0x2D, 0x9E, 0x5B, 0x0E, 0x96, 0xAA, +0x97, 0xE6, 0x97, 0x0E, 0x6E, 0x0D, 0xD9, 0xDA, 0xB4, 0x0D, +0xDF, 0x56, 0xB4, 0xED, 0xF5, 0xF6, 0x45, 0xDB, 0x2F, 0x97, +0xCD, 0x28, 0xDB, 0xBB, 0x83, 0xB6, 0x43, 0xB9, 0xA3, 0xBF, +0x3C, 0xB8, 0xBC, 0x65, 0xA7, 0xC9, 0xCE, 0xCD, 0x3B, 0x3F, +0x54, 0xA4, 0x54, 0xF4, 0x54, 0xFA, 0x54, 0x36, 0xEE, 0xD2, +0xDD, 0xB5, 0x61, 0xD7, 0xF8, 0x6E, 0xD1, 0xEE, 0x1B, 0x7B, +0xBC, 0xF6, 0x34, 0xEC, 0xD5, 0xDB, 0x5B, 0xBC, 0xF7, 0xFD, +0x3E, 0xC9, 0xBE, 0xDB, 0x55, 0x01, 0x55, 0x4D, 0xD5, 0x66, +0xD5, 0x65, 0xFB, 0x49, 0xFB, 0xB3, 0xF7, 0x3F, 0xAE, 0x89, +0xAA, 0xE9, 0xF8, 0x96, 0xFB, 0x6D, 0x5D, 0xAD, 0x4E, 0x6D, +0x71, 0xED, 0xC7, 0x03, 0xD2, 0x03, 0xFD, 0x07, 0x23, 0x0E, +0xB6, 0xD7, 0xB9, 0xD4, 0xD5, 0x1D, 0xD2, 0x3D, 0x54, 0x52, +0x8F, 0xD6, 0x2B, 0xEB, 0x47, 0x0E, 0xC7, 0x1F, 0xBE, 0xFE, +0x9D, 0xEF, 0x77, 0x2D, 0x0D, 0x36, 0x0D, 0x55, 0x8D, 0x9C, +0xC6, 0xE2, 0x23, 0x70, 0x44, 0x79, 0xE4, 0xE9, 0xF7, 0x09, +0xDF, 0xF7, 0x1E, 0x0D, 0x3A, 0xDA, 0x76, 0x8C, 0x7B, 0xAC, +0xE1, 0x07, 0xD3, 0x1F, 0x76, 0x1D, 0x67, 0x1D, 0x2F, 0x6A, +0x42, 0x9A, 0xF2, 0x9A, 0x46, 0x9B, 0x53, 0x9A, 0xFB, 0x5B, +0x62, 0x5B, 0xBA, 0x4F, 0xCC, 0x3E, 0xD1, 0xD6, 0xEA, 0xDE, +0x7A, 0xFC, 0x47, 0xDB, 0x1F, 0x0F, 0x9C, 0x34, 0x3C, 0x59, +0x79, 0x4A, 0xF3, 0x54, 0xC9, 0x69, 0xDA, 0xE9, 0x82, 0xD3, +0x93, 0x67, 0xF2, 0xCF, 0x8C, 0x9D, 0x95, 0x9D, 0x7D, 0x7E, +0x2E, 0xF9, 0xDC, 0x60, 0xDB, 0xA2, 0xB6, 0x7B, 0xE7, 0x63, +0xCE, 0xDF, 0x6A, 0x0F, 0x6F, 0xEF, 0xBA, 0x10, 0x74, 0xE1, +0xD2, 0x45, 0xFF, 0x8B, 0xE7, 0x3B, 0xBC, 0x3B, 0xCE, 0x5C, +0xF2, 0xB8, 0x74, 0xF2, 0xB2, 0xDB, 0xE5, 0x13, 0x57, 0xB8, +0x57, 0x9A, 0xAF, 0x3A, 0x5F, 0x6D, 0xEA, 0x74, 0xEA, 0x3C, +0xFE, 0x93, 0xD3, 0x4F, 0xC7, 0xBB, 0x9C, 0xBB, 0x9A, 0xAE, +0xB9, 0x5C, 0x6B, 0xB9, 0xEE, 0x7A, 0xBD, 0xB5, 0x7B, 0x66, +0xF7, 0xE9, 0x1B, 0x9E, 0x37, 0xCE, 0xDD, 0xF4, 0xBD, 0x79, +0xF1, 0x16, 0xFF, 0xD6, 0xD5, 0x9E, 0x39, 0x3D, 0xDD, 0xBD, +0xF3, 0x7A, 0x6F, 0xF7, 0xC5, 0xF7, 0xF5, 0xDF, 0x16, 0xDD, +0x7E, 0x72, 0x27, 0xFD, 0xCE, 0xCB, 0xBB, 0xD9, 0x77, 0x27, +0xEE, 0xAD, 0xBC, 0x4F, 0xBC, 0x5F, 0xF4, 0x40, 0xED, 0x41, +0xD9, 0x43, 0xDD, 0x87, 0xD5, 0x3F, 0x5B, 0xFE, 0xDC, 0xD8, +0xEF, 0xDC, 0x7F, 0x6A, 0xC0, 0x77, 0xA0, 0xF3, 0xD1, 0xDC, +0x47, 0xF7, 0x06, 0x85, 0x83, 0xCF, 0xFE, 0x91, 0xF5, 0x8F, +0x0F, 0x43, 0x05, 0x8F, 0x99, 0x8F, 0xCB, 0x86, 0x0D, 0x86, +0xEB, 0x9E, 0x38, 0x3E, 0x39, 0x39, 0xE2, 0x3F, 0x72, 0xFD, +0xE9, 0xFC, 0xA7, 0x43, 0xCF, 0x64, 0xCF, 0x26, 0x9E, 0x17, +0xFE, 0xA2, 0xFE, 0xCB, 0xAE, 0x17, 0x16, 0x2F, 0x7E, 0xF8, +0xD5, 0xEB, 0xD7, 0xCE, 0xD1, 0x98, 0xD1, 0xA1, 0x97, 0xF2, +0x97, 0x93, 0xBF, 0x6D, 0x7C, 0xA5, 0xFD, 0xEA, 0xC0, 0xEB, +0x19, 0xAF, 0xDB, 0xC6, 0xC2, 0xC6, 0x1E, 0xBE, 0xC9, 0x78, +0x33, 0x31, 0x5E, 0xF4, 0x56, 0xFB, 0xED, 0xC1, 0x77, 0xDC, +0x77, 0x1D, 0xEF, 0xA3, 0xDF, 0x0F, 0x4F, 0xE4, 0x7C, 0x20, +0x7F, 0x28, 0xFF, 0x68, 0xF9, 0xB1, 0xF5, 0x53, 0xD0, 0xA7, +0xFB, 0x93, 0x19, 0x93, 0x93, 0xFF, 0x04, 0x03, 0x98, 0xF3, +0xFC, 0x63, 0x33, 0x2D, 0xDB, 0x00, 0x00, 0x00, 0x20, 0x63, +0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x25, 0x00, 0x00, 0x80, +0x83, 0x00, 0x00, 0xF9, 0xFF, 0x00, 0x00, 0x80, 0xE9, 0x00, +0x00, 0x75, 0x30, 0x00, 0x00, 0xEA, 0x60, 0x00, 0x00, 0x3A, +0x98, 0x00, 0x00, 0x17, 0x6F, 0x92, 0x5F, 0xC5, 0x46, 0x00, +0x00, 0x09, 0x20, 0x49, 0x44, 0x41, 0x54, 0x78, 0xDA, 0x9C, +0x97, 0x7F, 0x90, 0x5E, 0x65, 0x75, 0xC7, 0x3F, 0xE7, 0x3C, +0x3F, 0xEE, 0x8F, 0xF7, 0x7D, 0xF7, 0x67, 0xC8, 0x86, 0xD0, +0x95, 0x60, 0x48, 0x03, 0x6A, 0x90, 0x08, 0xE3, 0x80, 0x44, +0x99, 0xA0, 0x16, 0xE5, 0x87, 0x05, 0x6B, 0x07, 0x61, 0xFC, +0xC3, 0x01, 0x9D, 0x01, 0x95, 0x4E, 0xF9, 0xA3, 0xA5, 0x33, +0xB6, 0x76, 0x3A, 0xC2, 0x50, 0x99, 0x71, 0x44, 0x51, 0x92, +0x51, 0x0B, 0x28, 0x30, 0xAD, 0x75, 0x2A, 0x19, 0x61, 0x6C, +0x1D, 0x48, 0x75, 0x87, 0x76, 0xA8, 0xA8, 0x24, 0x1A, 0x24, +0x1A, 0xC2, 0xC6, 0x00, 0xD9, 0x24, 0xCB, 0x66, 0xB3, 0xBB, +0xEF, 0xEE, 0xFB, 0xEB, 0xDE, 0xFB, 0x3C, 0xFD, 0xE3, 0x5D, +0x62, 0x77, 0x5A, 0x65, 0xEB, 0x77, 0xE6, 0xCE, 0xDC, 0xE7, +0xDC, 0x7B, 0x9F, 0xF3, 0x3D, 0xCF, 0x73, 0xEE, 0xF7, 0x9C, +0x47, 0x1E, 0x7D, 0xF4, 0x51, 0x76, 0xEE, 0xD8, 0x71, 0xF1, +0xA5, 0xEF, 0xBD, 0xE2, 0xF1, 0x10, 0x24, 0xB1, 0xCE, 0x11, +0x45, 0x00, 0x20, 0xC6, 0xFE, 0xC5, 0xF2, 0xB8, 0x6F, 0x3C, +0x75, 0x27, 0xA2, 0x88, 0x48, 0xFF, 0x71, 0x84, 0x18, 0x03, +0x11, 0xF9, 0xCD, 0xEB, 0x21, 0xAE, 0xF8, 0x46, 0x80, 0xB2, +0x2C, 0x50, 0xA1, 0x3B, 0xF1, 0xE4, 0xF7, 0xAE, 0xBA, 0xF9, +0x96, 0x5B, 0x9E, 0xB6, 0xCE, 0xE8, 0xA5, 0x7B, 0x0E, 0xBE, +0xBA, 0xAB, 0xB1, 0x61, 0x7A, 0xE8, 0xFA, 0x0F, 0xBC, 0x9B, +0xA2, 0x0C, 0x20, 0x86, 0x28, 0x20, 0x21, 0x10, 0x89, 0xC8, +0xF2, 0x8C, 0x71, 0x99, 0x94, 0x8A, 0xE0, 0xD3, 0x94, 0xB9, +0xB9, 0x79, 0x9A, 0x0B, 0xF3, 0x20, 0x4A, 0x92, 0x24, 0x8C, +0x8E, 0x8E, 0x22, 0x22, 0xF4, 0x8A, 0xA2, 0xEF, 0x30, 0x86, +0x95, 0xA4, 0x63, 0xC4, 0x59, 0xE5, 0x1F, 0x77, 0x3D, 0x51, +0xDB, 0x73, 0x60, 0xFA, 0x7B, 0xCE, 0xE8, 0x35, 0x76, 0xFF, +0xE4, 0xD4, 0x63, 0xED, 0x90, 0x34, 0x6E, 0xBD, 0xE9, 0x3A, +0xD2, 0xC4, 0xD3, 0x2B, 0x2A, 0x40, 0x41, 0x5E, 0x63, 0xFD, +0x5A, 0x78, 0x10, 0x55, 0x50, 0xA0, 0x96, 0xD7, 0xF8, 0xF1, +0x33, 0xFF, 0xC5, 0xA1, 0x83, 0xFB, 0xD1, 0x58, 0x22, 0xAA, +0xF4, 0x8A, 0x92, 0xE3, 0x03, 0x43, 0x5C, 0xF2, 0xAE, 0xF7, +0x30, 0x3C, 0x3C, 0xC2, 0xD2, 0xD2, 0x22, 0x88, 0xF4, 0xE3, +0x0E, 0x11, 0x11, 0x88, 0x12, 0xF1, 0x2A, 0xDC, 0xFA, 0xF1, +0xEB, 0xF9, 0xFE, 0xBF, 0x3F, 0x35, 0xB4, 0x7F, 0x72, 0xEA, +0x31, 0xFB, 0xCA, 0xF1, 0x59, 0xBB, 0xE5, 0xBC, 0xB7, 0x30, +0x7D, 0x62, 0x9E, 0xA5, 0x6E, 0x44, 0x8C, 0x25, 0xA2, 0x20, +0x10, 0x43, 0x58, 0x5E, 0x6A, 0x21, 0x56, 0x15, 0x36, 0xF1, +0x64, 0x69, 0xCE, 0x93, 0x8F, 0xFC, 0x03, 0x23, 0x59, 0xC5, +0xC7, 0x6E, 0xBA, 0x91, 0xB3, 0xCE, 0x7A, 0x23, 0x00, 0x0B, +0x0B, 0xF3, 0xEC, 0xDE, 0xBD, 0x9B, 0x1D, 0x5F, 0xFE, 0x02, +0xEF, 0x78, 0xEF, 0x07, 0x19, 0xDF, 0xB0, 0x91, 0xE6, 0xC2, +0x02, 0xC6, 0x18, 0x42, 0x08, 0x40, 0x44, 0x55, 0x08, 0x45, +0x41, 0x3D, 0x81, 0x2D, 0xE7, 0xBD, 0x85, 0x57, 0x8E, 0x9F, +0xB4, 0xD6, 0xF8, 0x7A, 0xE8, 0x52, 0xE7, 0xC8, 0x4C, 0x9B, +0x66, 0x61, 0x50, 0x13, 0x29, 0x81, 0x10, 0x22, 0xCE, 0x19, +0xAC, 0x4F, 0x89, 0x40, 0xD1, 0x29, 0xA9, 0x0F, 0x26, 0x3C, +0xFD, 0xF8, 0xB7, 0xD9, 0xB6, 0x69, 0x88, 0x3F, 0xFB, 0xF3, +0xDB, 0xF8, 0x9F, 0x18, 0x18, 0x18, 0xE4, 0xDA, 0x6B, 0x3F, +0xC8, 0x39, 0x9B, 0x37, 0xF3, 0xE9, 0x3B, 0x3E, 0xCF, 0xE6, +0x6D, 0x7F, 0x42, 0xBD, 0x31, 0x48, 0x51, 0xB6, 0x91, 0xE5, +0x20, 0x8C, 0x2A, 0x45, 0xBB, 0xC5, 0x50, 0x0A, 0xBD, 0xD8, +0xC0, 0x24, 0xF5, 0x60, 0xD5, 0xD5, 0x98, 0xEF, 0x35, 0x78, +0x69, 0xA6, 0xCB, 0x52, 0x70, 0x88, 0x03, 0x49, 0x6A, 0xA8, +0xB5, 0x34, 0x5F, 0x9D, 0x65, 0xEA, 0x3F, 0xBF, 0x81, 0xA9, +0xAF, 0xE1, 0xDC, 0xCB, 0xAE, 0xE7, 0x27, 0x13, 0x4F, 0xB1, +0x31, 0xEB, 0xF0, 0x89, 0x4F, 0x7C, 0x92, 0xDF, 0x86, 0x73, +0xDF, 0xF4, 0x66, 0xFE, 0xF2, 0x53, 0x37, 0x72, 0xDB, 0xE7, +0x1E, 0x64, 0xEB, 0xD5, 0x1F, 0xA7, 0x6A, 0x17, 0xFD, 0x44, +0x05, 0x62, 0xD9, 0xA3, 0xE8, 0x74, 0x68, 0x26, 0x96, 0x66, +0x39, 0x82, 0xBA, 0x1A, 0x56, 0xAD, 0x67, 0xB1, 0xDB, 0xE0, +0xF0, 0x74, 0x97, 0xB6, 0x06, 0x74, 0x20, 0x67, 0xEE, 0xD0, +0x3E, 0xDA, 0xD3, 0x2F, 0x33, 0x77, 0xE4, 0x30, 0x0F, 0xDD, +0xF9, 0x31, 0x9E, 0x7A, 0xFA, 0xC7, 0x3C, 0xF2, 0x83, 0x1F, +0x90, 0x4F, 0xFF, 0x94, 0xFB, 0x1F, 0xF8, 0x1C, 0xD6, 0x7B, +0x7E, 0x17, 0x2E, 0x7A, 0xC7, 0x36, 0xAE, 0x7A, 0xFB, 0x04, +0x8F, 0xEF, 0x7D, 0x96, 0x33, 0xCE, 0x7E, 0x1B, 0x9D, 0xA5, +0x45, 0xAC, 0x31, 0x14, 0xDD, 0x82, 0xD0, 0x81, 0xA6, 0x96, +0xB4, 0xCA, 0x51, 0xAC, 0x49, 0x50, 0x35, 0x86, 0xA5, 0x22, +0x67, 0x6A, 0x36, 0x30, 0x5B, 0x64, 0xBC, 0x74, 0xE4, 0x28, +0xE7, 0x96, 0x87, 0xB8, 0xF3, 0x86, 0x0B, 0xD9, 0x54, 0x5F, +0x60, 0xBE, 0xB9, 0xC4, 0xAD, 0x9F, 0xBC, 0x99, 0x43, 0x4F, +0xDC, 0xCF, 0x15, 0xEF, 0xBC, 0x80, 0xD1, 0xB5, 0xEB, 0x59, +0x0D, 0xDE, 0x79, 0xD1, 0xDB, 0x99, 0x69, 0x2D, 0x31, 0xDD, +0x35, 0xCC, 0xB4, 0x61, 0xBA, 0x15, 0x99, 0x5E, 0x8C, 0x4C, +0x37, 0x23, 0x47, 0x4F, 0x0A, 0xAD, 0x22, 0x45, 0xAD, 0x60, +0xAD, 0x85, 0x6E, 0x35, 0xC8, 0xD1, 0x79, 0x25, 0xC9, 0x32, +0x16, 0x7B, 0x2D, 0xB0, 0x05, 0x97, 0x5F, 0xF9, 0x01, 0x2E, +0xDE, 0xF6, 0x2E, 0x0E, 0xBF, 0xF4, 0x32, 0x59, 0x96, 0x73, +0xD9, 0x85, 0x1B, 0x09, 0xDD, 0x05, 0x56, 0x8B, 0xD9, 0x93, +0x73, 0x1C, 0x79, 0x65, 0x8A, 0xB8, 0x41, 0x31, 0x65, 0x42, +0x59, 0x16, 0x48, 0x95, 0xA2, 0xD1, 0xD3, 0x6C, 0x16, 0x2C, +0xF5, 0x12, 0x44, 0x4A, 0x14, 0x2A, 0x8A, 0x90, 0x33, 0xD7, +0xAB, 0x71, 0xB2, 0x15, 0x89, 0x6B, 0x37, 0xF1, 0xCF, 0x87, +0xC7, 0xD8, 0x71, 0xDF, 0x4E, 0x06, 0x06, 0x87, 0xD8, 0xB2, +0x65, 0x0B, 0x00, 0xF7, 0xDE, 0xFB, 0x25, 0xCE, 0x3F, 0xFF, +0x3C, 0xAA, 0xAA, 0x5A, 0x15, 0x81, 0x8B, 0x2E, 0xB9, 0x84, +0xF7, 0x8F, 0xB5, 0x99, 0x3A, 0x72, 0x8C, 0xD9, 0xE0, 0x98, +0xAF, 0x2C, 0x4D, 0x12, 0xE6, 0x0A, 0xC7, 0xCC, 0x52, 0xA4, +0x53, 0x08, 0x22, 0x01, 0x2B, 0x52, 0x12, 0xC5, 0x82, 0x1D, +0x82, 0x24, 0xA5, 0x52, 0x21, 0x0C, 0xAD, 0x67, 0x61, 0x71, +0x6A, 0xC5, 0x84, 0xE3, 0xE3, 0xE3, 0x8C, 0x8F, 0x8F, 0x13, +0x63, 0x5C, 0x15, 0x81, 0x75, 0xA7, 0xAF, 0xE7, 0xAA, 0x4B, +0xDE, 0xC6, 0xEE, 0x89, 0x79, 0xF2, 0xB3, 0x37, 0x53, 0x2D, +0x75, 0x28, 0x3B, 0x25, 0x65, 0xAB, 0x45, 0x37, 0x96, 0x40, +0x1B, 0xA1, 0x85, 0x8A, 0x46, 0xCC, 0x60, 0x8A, 0xAB, 0x37, +0x88, 0x46, 0x30, 0x3E, 0xA1, 0x1E, 0x8F, 0xF2, 0xEE, 0x4B, +0xB7, 0xFE, 0x9F, 0x13, 0xBF, 0x96, 0xD1, 0xAB, 0xC1, 0x73, +0x07, 0x0F, 0x12, 0xD7, 0xAF, 0xC3, 0xF9, 0x84, 0xA4, 0x5E, +0xC3, 0xE5, 0x19, 0xB6, 0x56, 0x23, 0xA9, 0x0F, 0x83, 0xF7, +0x7D, 0x6D, 0x80, 0x88, 0x6D, 0x24, 0xB8, 0xA1, 0x01, 0x92, +0x7A, 0x4E, 0x96, 0x67, 0xB4, 0xCE, 0xB8, 0x90, 0xAF, 0x3E, +0xF0, 0x5D, 0x28, 0xBB, 0xFC, 0x3E, 0x58, 0x9A, 0x9B, 0xE1, +0xA1, 0x9D, 0x5F, 0xE6, 0x5F, 0x8F, 0x66, 0xAC, 0xD9, 0x7C, +0x0E, 0x46, 0x05, 0x75, 0x16, 0x9F, 0xA7, 0x7D, 0x1F, 0xA7, +0xAD, 0x41, 0x73, 0x0F, 0x02, 0x4A, 0x04, 0x5C, 0x44, 0x6C, +0x85, 0xCF, 0x13, 0x94, 0x8A, 0xC6, 0x99, 0x6F, 0x64, 0x57, +0xF1, 0x87, 0xFC, 0xC5, 0xA7, 0xEF, 0xE0, 0x97, 0x3F, 0xDF, +0xCB, 0xD4, 0xE1, 0xC9, 0xFF, 0x17, 0x81, 0xBB, 0xBF, 0xB8, +0x83, 0x1B, 0x27, 0x0A, 0xAA, 0xF7, 0xDC, 0x4C, 0x6E, 0x1D, +0x6A, 0x04, 0xE7, 0x15, 0xE7, 0x2D, 0x62, 0x05, 0x4C, 0x40, +0xFD, 0x72, 0x5D, 0x01, 0xB0, 0xA9, 0x80, 0x54, 0xA0, 0x81, +0x24, 0x73, 0x0C, 0x58, 0x65, 0xE4, 0xB2, 0x0F, 0xF3, 0x2D, +0x7B, 0x31, 0xEF, 0xBF, 0xFB, 0xBB, 0x5C, 0x76, 0xF3, 0x5D, +0x7C, 0x6D, 0xE7, 0x4E, 0x62, 0xB1, 0x8A, 0x15, 0x89, 0x81, +0x12, 0xC7, 0xA0, 0x7A, 0xAC, 0x17, 0x7C, 0x62, 0x70, 0x5E, +0x11, 0x13, 0xA9, 0x42, 0x97, 0x10, 0x7A, 0x54, 0x55, 0x0B, +0xC9, 0x40, 0x54, 0xFA, 0x2B, 0xA0, 0x99, 0x62, 0x32, 0x03, +0x5A, 0xA1, 0x4E, 0x70, 0x4E, 0x91, 0x66, 0x93, 0xE1, 0x73, +0x2E, 0x60, 0xE4, 0x8F, 0x6F, 0x43, 0xAF, 0xFB, 0x2C, 0xB7, +0x3F, 0xD3, 0xE5, 0xF6, 0xBF, 0xB9, 0x83, 0xAA, 0xF7, 0x3A, +0x24, 0x44, 0xB9, 0xF3, 0x6F, 0xFF, 0x8A, 0xAF, 0x5D, 0x39, +0x48, 0xEF, 0x5F, 0xFE, 0x9E, 0x66, 0xB9, 0x80, 0x49, 0x95, +0x48, 0x45, 0x94, 0x80, 0xDA, 0x88, 0xF1, 0x8A, 0xFA, 0x7E, +0xAD, 0xD1, 0x18, 0x22, 0xB1, 0x2A, 0xF0, 0xB9, 0xC7, 0x18, +0x41, 0x63, 0x85, 0xF3, 0x4A, 0xAD, 0x96, 0x52, 0x76, 0xDA, +0x74, 0x4E, 0xCE, 0xE0, 0xA4, 0x62, 0xFD, 0xFB, 0x3E, 0xC2, +0xFD, 0x33, 0x6B, 0x78, 0xF8, 0xE1, 0x47, 0x56, 0xB5, 0x0D, +0xD7, 0xDE, 0xF0, 0x11, 0xBE, 0x72, 0xC3, 0x45, 0x94, 0x4F, +0xDC, 0x4F, 0x17, 0xC1, 0x5A, 0xC1, 0x3B, 0xC1, 0x18, 0xC1, +0x98, 0x88, 0x9A, 0x7E, 0x9F, 0xA1, 0x04, 0x50, 0x2A, 0x44, +0xC0, 0x1A, 0x88, 0xA1, 0xC4, 0x02, 0xCE, 0x09, 0xA9, 0x33, +0x24, 0x4E, 0xA1, 0xD7, 0xC5, 0x17, 0x1D, 0x06, 0x36, 0x5C, +0xC8, 0x89, 0x66, 0x7B, 0xD5, 0xB9, 0xF0, 0x47, 0x1F, 0xBA, +0x8E, 0xAB, 0xD7, 0x09, 0x9D, 0xE3, 0x87, 0x70, 0xDE, 0x62, +0x8D, 0x62, 0x9D, 0xA0, 0xCE, 0x60, 0xAC, 0x20, 0x44, 0x2C, +0x11, 0x62, 0x59, 0x62, 0x24, 0x90, 0xD5, 0x52, 0x92, 0xDC, +0x82, 0x04, 0x08, 0x90, 0x26, 0x0E, 0x6B, 0x94, 0x4E, 0xA7, +0x87, 0x58, 0x43, 0xBE, 0xF0, 0x0A, 0x1B, 0xCE, 0x1C, 0x5A, +0x35, 0x81, 0xD0, 0x5E, 0xE0, 0xE5, 0xF9, 0x2E, 0xF9, 0xE6, +0x61, 0x52, 0x03, 0xD9, 0x40, 0x8D, 0xD0, 0xAD, 0x20, 0x33, +0xF8, 0x01, 0x07, 0x11, 0x34, 0xC6, 0x88, 0x18, 0x30, 0x89, +0xC3, 0x3A, 0x8F, 0xA1, 0x5F, 0x36, 0xBD, 0x35, 0x28, 0x91, +0x50, 0x95, 0xA4, 0xA9, 0x47, 0x55, 0x81, 0x80, 0xAE, 0x52, +0x06, 0x4E, 0x1C, 0x3B, 0xCA, 0x2D, 0x7F, 0x7D, 0x37, 0xFB, +0x37, 0x6C, 0x63, 0xF4, 0xB4, 0x35, 0x84, 0xAA, 0x42, 0x55, +0x49, 0xB3, 0x0C, 0x11, 0xA1, 0xEC, 0xF4, 0x15, 0x55, 0x79, +0xAD, 0xEF, 0x51, 0x45, 0x55, 0x40, 0x85, 0x10, 0x2A, 0xDA, +0x9D, 0x0E, 0x65, 0x55, 0x50, 0x55, 0x25, 0x45, 0xAF, 0x87, +0x12, 0x88, 0x6B, 0x36, 0x30, 0x39, 0x3B, 0xBF, 0x2A, 0x02, +0x3F, 0xFA, 0xC9, 0x4F, 0xD9, 0xD5, 0x5E, 0xC7, 0xDA, 0xF3, +0xB7, 0x53, 0x34, 0x17, 0x31, 0xC6, 0x40, 0x8C, 0x74, 0xDB, +0x6D, 0x8C, 0x77, 0x18, 0xA7, 0x10, 0xC1, 0x02, 0xA8, 0x11, +0x42, 0x08, 0x14, 0x45, 0x05, 0xAA, 0x58, 0xA3, 0x38, 0xE7, +0x88, 0x21, 0xE0, 0xBC, 0x25, 0x84, 0x08, 0xD1, 0x21, 0xA3, +0x23, 0x1C, 0x7C, 0x71, 0xB6, 0xDF, 0xA8, 0xBE, 0x8E, 0x22, +0xCE, 0x2E, 0x75, 0x19, 0x1D, 0x1D, 0xC3, 0x55, 0x01, 0xBC, +0x27, 0x8A, 0xD2, 0xED, 0x74, 0x89, 0x21, 0xA2, 0xCE, 0xA1, +0xDE, 0x12, 0xE3, 0xB2, 0x10, 0x89, 0x80, 0x11, 0x08, 0x45, +0x8F, 0x58, 0x15, 0xA8, 0x51, 0x8C, 0x0A, 0x84, 0x0A, 0xEF, +0x2D, 0x02, 0xA8, 0x04, 0x12, 0x55, 0x8E, 0xB5, 0xA0, 0xAA, +0x8A, 0xD7, 0xD1, 0x82, 0x8A, 0x3D, 0xFB, 0x7E, 0x41, 0x3A, +0x3C, 0x86, 0xB3, 0x10, 0x42, 0x85, 0x55, 0x21, 0x96, 0x15, +0xD6, 0x0A, 0xC6, 0x82, 0x51, 0xB3, 0xBC, 0x05, 0x22, 0xA8, +0x82, 0x33, 0x81, 0x3C, 0x4B, 0xA8, 0xE7, 0x19, 0x59, 0xEA, +0xF0, 0x56, 0xB0, 0x02, 0x86, 0x48, 0x96, 0x58, 0x9C, 0x01, +0x35, 0x81, 0xB5, 0xB9, 0x62, 0xEC, 0xCA, 0x86, 0x64, 0xEF, +0xDE, 0xBD, 0x34, 0x9B, 0xCD, 0x53, 0xE3, 0x93, 0xD3, 0xC7, +0x99, 0x78, 0xE1, 0x55, 0x46, 0x36, 0xBE, 0x19, 0xAD, 0x7A, +0xE4, 0x89, 0xC5, 0x68, 0x20, 0xF1, 0x86, 0x34, 0x71, 0xA4, +0xDE, 0x22, 0x31, 0x10, 0x01, 0x15, 0x15, 0xAC, 0xB7, 0x78, +0x13, 0x49, 0x13, 0x83, 0xB5, 0x91, 0xCC, 0x28, 0x79, 0xEA, +0x70, 0x3E, 0x12, 0xCB, 0x2E, 0x96, 0x0A, 0xE3, 0x02, 0xA1, +0xDD, 0x61, 0x7C, 0x28, 0xF9, 0x5F, 0x01, 0xDF, 0x73, 0xCF, +0x3D, 0x1C, 0x38, 0x70, 0xE0, 0xD4, 0xF8, 0x97, 0xBF, 0x7A, +0x9E, 0x13, 0xB6, 0x41, 0x7D, 0xA8, 0x86, 0x21, 0xE0, 0x14, +0x24, 0x14, 0x64, 0x5E, 0x69, 0x34, 0x32, 0xBC, 0x06, 0x84, +0xAA, 0xFF, 0x17, 0x84, 0x10, 0x70, 0x12, 0xA9, 0xD7, 0x12, +0xBC, 0x89, 0xE4, 0x4E, 0x70, 0x2E, 0xE2, 0x4C, 0x24, 0xB3, +0x86, 0xCC, 0x19, 0x52, 0x2F, 0x8C, 0x0C, 0x35, 0xE8, 0xED, +0xFB, 0x0F, 0xB6, 0x6C, 0x38, 0x63, 0x85, 0xF3, 0xC5, 0xC5, +0x45, 0xA6, 0xA7, 0xA7, 0x19, 0x1B, 0x1B, 0x3B, 0x65, 0x7B, +0xD3, 0x96, 0xAD, 0x5C, 0xF3, 0x06, 0xE1, 0xD7, 0x0F, 0xDD, +0x81, 0x4A, 0x9B, 0xD4, 0x43, 0xE6, 0x0D, 0x59, 0x6A, 0x30, +0x94, 0xB8, 0xD8, 0x45, 0xCB, 0x62, 0x39, 0x07, 0x44, 0x30, +0x22, 0xE4, 0x4E, 0x48, 0xAD, 0xA0, 0xA1, 0xC0, 0x11, 0xC8, +0x9D, 0x52, 0x4B, 0x2D, 0xB9, 0x37, 0x9C, 0x36, 0xD2, 0x60, +0xE6, 0x99, 0xDD, 0x9C, 0xB3, 0xF4, 0x0B, 0xB6, 0x5F, 0x7E, +0xF9, 0x0A, 0x02, 0x93, 0x93, 0x93, 0xD4, 0x6A, 0x35, 0x46, +0x46, 0x46, 0x4E, 0xD9, 0x06, 0x87, 0x47, 0xF9, 0xC2, 0x9D, +0x7F, 0xC7, 0x7D, 0xD7, 0x5F, 0xCC, 0xFC, 0x13, 0x0F, 0x33, +0x76, 0xDA, 0x30, 0x43, 0xF5, 0xAC, 0x1F, 0x8C, 0x8D, 0x64, +0x36, 0x60, 0x35, 0xF6, 0xAB, 0x61, 0x8C, 0x11, 0x9F, 0x38, +0x52, 0x2F, 0x68, 0xD9, 0x25, 0xB1, 0x7D, 0x05, 0x34, 0xB1, +0xAF, 0x52, 0x89, 0x33, 0xF4, 0x4E, 0xCC, 0x30, 0xFA, 0xE2, +0x04, 0xDF, 0xF8, 0xD2, 0x5D, 0x34, 0x06, 0x87, 0x57, 0x10, +0xE8, 0xF6, 0x7A, 0x1C, 0x3F, 0x76, 0x94, 0x3C, 0x4B, 0x57, +0xEE, 0x8B, 0x5A, 0xC6, 0xCF, 0xDA, 0x8C, 0x54, 0x3D, 0x5C, +0x04, 0x2F, 0xB1, 0x2F, 0x46, 0xCE, 0x30, 0x50, 0xCF, 0xF0, +0x56, 0x99, 0x6B, 0x15, 0xD8, 0xAA, 0x0A, 0x0A, 0x50, 0x4F, +0x2D, 0xA5, 0x4D, 0x70, 0x56, 0x29, 0x5B, 0x2D, 0xD4, 0x28, +0x99, 0x75, 0x78, 0xEF, 0x28, 0xDA, 0x15, 0x59, 0x9A, 0x90, +0xE5, 0xB5, 0x15, 0x67, 0xC4, 0x76, 0x73, 0x9E, 0xE7, 0xF7, +0xEC, 0x61, 0x52, 0xD6, 0xF0, 0xF5, 0x47, 0xBE, 0x8D, 0x35, +0xCA, 0x70, 0xE6, 0xA8, 0x25, 0x96, 0x5E, 0x10, 0xBE, 0xF9, +0xD8, 0x93, 0xAC, 0xDD, 0x7E, 0x13, 0xF4, 0x3A, 0xD8, 0x18, +0x31, 0x46, 0x91, 0xE5, 0x46, 0x34, 0x02, 0xB9, 0x15, 0xB5, +0xEB, 0x06, 0x6C, 0x79, 0xF4, 0xE0, 0x34, 0xCE, 0xA4, 0x64, +0x26, 0xA2, 0xD6, 0x50, 0xC6, 0x88, 0xB1, 0x16, 0x63, 0x2D, +0xAA, 0x86, 0xC6, 0xFA, 0x37, 0xF0, 0xDC, 0xC0, 0x46, 0xEE, +0xFA, 0xCC, 0x67, 0x38, 0x6F, 0xEB, 0x05, 0xBC, 0x30, 0x75, +0x84, 0x67, 0xF7, 0xFF, 0x9A, 0xCA, 0x0D, 0xD0, 0x49, 0x47, +0xB9, 0xF2, 0xF6, 0x7B, 0xF9, 0xB7, 0x03, 0xCF, 0x01, 0x60, +0xAA, 0x0E, 0x21, 0x2C, 0x81, 0x1A, 0x06, 0xB7, 0x7F, 0x94, +0xB5, 0x67, 0x6F, 0xA6, 0xDB, 0xEE, 0x91, 0x79, 0x47, 0x08, +0xE0, 0x10, 0xAA, 0x90, 0x70, 0x6C, 0xEA, 0x38, 0xEB, 0xCF, +0xF4, 0xA5, 0xDD, 0xF4, 0x07, 0xC3, 0x57, 0xD7, 0xFF, 0xE9, +0xC9, 0x5D, 0x13, 0xDF, 0x77, 0x43, 0x5B, 0xCF, 0x5E, 0x8F, +0x7A, 0x07, 0xA1, 0x22, 0x86, 0x88, 0x18, 0x03, 0x46, 0x51, +0x51, 0x06, 0xCF, 0x78, 0x2B, 0xDF, 0xF9, 0x59, 0xE4, 0xC1, +0x6F, 0xBD, 0x40, 0x6D, 0x74, 0x98, 0x35, 0x63, 0xDB, 0x71, +0x59, 0x4E, 0x6D, 0x68, 0x84, 0xF6, 0xB1, 0x39, 0xF2, 0xC1, +0x71, 0xD4, 0x1A, 0xC4, 0x9A, 0xBE, 0xEC, 0x1A, 0x21, 0x04, +0x78, 0x79, 0xDF, 0xF3, 0x08, 0x91, 0x10, 0x2A, 0x62, 0x59, +0x11, 0x8B, 0x92, 0x3D, 0x93, 0x53, 0x34, 0x26, 0x7F, 0x38, +0xB7, 0xE9, 0x4F, 0xAF, 0xB8, 0xC6, 0x06, 0x31, 0x13, 0xEB, +0x8A, 0x5F, 0x5D, 0x71, 0xEC, 0xB9, 0xD3, 0x1F, 0xFF, 0xCE, +0xB3, 0x3F, 0x4F, 0x92, 0x91, 0x7A, 0x9F, 0x40, 0xAB, 0x0B, +0xA2, 0xFD, 0xC3, 0xA5, 0x11, 0x88, 0x60, 0x4C, 0x0A, 0x92, +0x73, 0xFC, 0x70, 0x93, 0x17, 0x0F, 0xEE, 0xEB, 0x1F, 0xC5, +0xAD, 0x05, 0x15, 0x62, 0xAF, 0x40, 0x8D, 0x40, 0x9E, 0x40, +0xD9, 0x43, 0x7A, 0x65, 0xBF, 0xBC, 0x9E, 0x2A, 0x1E, 0x91, +0x58, 0x55, 0x74, 0x5B, 0x1D, 0x86, 0x0D, 0xDD, 0xD3, 0xAB, +0x17, 0xAF, 0x0A, 0x62, 0x9F, 0xFE, 0xEF, 0x01, 0x00, 0x46, +0xBB, 0xB1, 0xB5, 0x3F, 0x50, 0x9D, 0x5B, 0x00, 0x00, 0x00, +0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 }; +