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 }; +