├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CMakeSettings.json ├── LICENSE ├── README.md ├── RemotePlayWhatever ├── CMakeLists.txt ├── ClickablePanel.cpp ├── ClickablePanel.h ├── FriendPanel.cpp ├── FriendPanel.h ├── FriendsListFrame.cpp ├── FriendsListFrame.h ├── QueueInviter.cpp ├── QueueInviter.h ├── RemoteApp.cpp ├── RemoteApp.h ├── RemotePlayInviteHandler.cpp ├── RemotePlayInviteHandler.h ├── RemotePlayWhatever.cpp ├── RemotePlayWhatever.h ├── SteamStuff.cpp ├── SteamStuff.h ├── appicon.ico ├── appicon.xpm ├── appresource.rc ├── wxSteamStuff.cpp └── wxSteamStuff.h └── assets └── rpw_screen.png /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | .vscode/ 3 | .cache/ 4 | out/ 5 | build/ 6 | build_debug/ 7 | CMakeLists.txt.user* 8 | CMakeCache.txt 9 | CMakeSettings.json 10 | CMakeFiles 11 | CMakeScripts 12 | Testing 13 | Makefile 14 | cmake_install.cmake 15 | install_manifest.txt 16 | compile_commands.json 17 | CTestTestfile.cmake 18 | _deps 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "open-steamworks"] 2 | path = open-steamworks 3 | url = https://github.com/m4dEngi/open-steamworks.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeList.txt : Top-level CMake project file, do global configuration 2 | # and include sub-projects here. 3 | # 4 | cmake_minimum_required (VERSION 3.8) 5 | 6 | project ("RemotePlayWhatever" VERSION 0.2.11) 7 | 8 | # Include sub-projects. 9 | add_subdirectory ("RemotePlayWhatever") 10 | -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "x86-Debug", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "buildRoot": "${projectDir}\\out\\build\\${name}", 8 | "installRoot": "${projectDir}\\out\\install\\${name}", 9 | "cmakeCommandArgs": "", 10 | "buildCommandArgs": "", 11 | "ctestCommandArgs": "", 12 | "inheritEnvironments": [ "msvc_x86" ], 13 | "variables": [] 14 | }, 15 | { 16 | "name": "x86-Release", 17 | "generator": "Ninja", 18 | "configurationType": "RelWithDebInfo", 19 | "buildRoot": "${projectDir}\\out\\build\\${name}", 20 | "installRoot": "${projectDir}\\out\\install\\${name}", 21 | "cmakeCommandArgs": "", 22 | "buildCommandArgs": "", 23 | "ctestCommandArgs": "", 24 | "inheritEnvironments": [ "msvc_x86" ], 25 | "variables": [] 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 m4dEngi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RemotePlayWhatever 2 | Tiny application that lets you force remote play together any game you have in your steam library including non-steam ones. 3 | 4 |

5 | RemotePlayWhatever screenshot 6 |

7 | 8 | ## How it works 9 | RemotePlayWhatever communicates with your running Steam client and instructs it to initiate a Remote Play Together session for the currently running game launched through Steam. It does this by using undocumented and potentially **unstable** internal Steam client APIs. 10 | 11 | ## ⚠️ Warning 12 | - This tool relies on internal Steam client APIs. Future Steam client updates **may break compatibility** without warning. 13 | - This project aims to support the latest **stable** version of the Steam client. If you encounter issues after a Steam update, please check for a new version of RemotePlayWhatever or report an issue. 14 | - **Use at Your Own Risk:** This tool communicates locally with Steam via its standard IPC channel and doesn't modify files. However, it relies on unstable, internal APIs used by the Steam client itself, not the stable APIs meant for games. These internal APIs can change with Steam updates, potentially breaking this tool without warning. 15 | 16 | ## Getting Started 17 | Download the latest RemotePlayWhatever [Release](https://github.com/m4dEngi/RemotePlayWhatever/releases/latest) for your system: 18 | - Linux: 19 | - **Arch**: A third-party [AUR package](https://aur.archlinux.org/packages/remoteplaywhatever) is available ( maintained by *Rojikku* ). 20 | - **Ubuntu**: Download and install the *.**deb** package. 21 | - **Any distro**: Download the *.**AppImage** and make it executable by running `chmod +x RemotePlayWhatever-*.AppImage`. \ 22 | *Note*: Some systems might require `fuse2` ( or alternative ) package to be installed for *AppImages* to work. 23 | - Windows: 24 | - Download and extract the RemotePlayWhatever-*.**zip** somewhere; no installation required. 25 | 26 | ... or [build the app from source](#building-from-source) 27 | 28 | ## Usage 29 | 1. Ensure the Steam client is running. 30 | 2. Launch RemotePlayWhatever. 31 | 3. Launch the game you want to play *through the Steam client*. 32 | 4. Alt+Tab (or switch) back to the RemotePlayWhatever window. 33 | 5. Invite your friend(s): 34 | - **Direct Invite:** Select a friend from the list. They will receive the invite link via a Steam Chat message. 35 | - **Guest Link:** Click the button to generate a guest invite link. The link will be automatically copied to your clipboard, ready for you to paste and share manually. 36 | 6. Alt+Tab (or switch) back to your game. 37 | 38 | ## Command line arguments 39 | ``` 40 | -a, --appid= AppID to use for non-steam games (Default is 480) 41 | -i, --invite= Send remote play invites to provided comma separated 42 | SteamID64s list ( use 0 for guest link ) 43 | -g, --guestid= Guest client id 44 | -c, --cancel= Cancel invite for provided SteamID64 and GuestID 45 | ``` 46 | 47 | ## Building from source 48 | ### Linux ( Debian ) 49 | 1. Install the dependencies: 50 | ```bash 51 | sudo apt update 52 | sudo apt install build-essential git cmake libwxgtk3.2-dev 53 | ``` 54 | 2. Clone the repository: 55 | ```bash 56 | git clone --recurse-submodules https://github.com/m4dEngi/RemotePlayWhatever.git 57 | cd RemotePlayWhatever 58 | ``` 59 | 3. Configure and build: 60 | ```bash 61 | cmake -B build -DCMAKE_BUILD_TYPE=Release 62 | cmake --build build 63 | ``` 64 | The executable will be placed in the `build/RemotePlayWhatever` directory. 65 | 4. **( optional )** Create and install deb package: 66 | ```bash 67 | cmake --build build --target package 68 | sudo dpkg -i build/RemotePlayWhatever-*-Linux.deb 69 | ``` 70 | 71 | ### Windows 72 | These instructions assume a 32-bit build using Visual Studio. \ 73 | All commands should be executed in a `Developer Command Prompt for VS`. 74 | 75 | 1. Download and install [Visual Studio](https://visualstudio.microsoft.com/) (Community Edition is free) with the "Desktop development with C++" workload installed and "Git For Windows" and "MSVC v142 - VS 2019 C++ x64/x86 build tools" components. 76 | 2. Download and install [wxWidgets](https://wxwidgets.org/) ( follow the docs ). 77 | 3. Clone the repository: 78 | ```bash 79 | git clone --recurse-submodules https://github.com/m4dEngi/RemotePlayWhatever.git && 80 | cd RemotePlayWhatever 81 | ``` 82 | 4. Configure and build: 83 | ```bash 84 | cmake -B build -A Win32 && 85 | cmake --build build --config Release 86 | ``` 87 | If build is successful, the executable will be created in the `build\RemotePlayWhatever\Release` folder. 88 | 89 | ## Contributing 90 | Contributions are welcome! If you find a bug or have a feature request, please open an issue. 91 | 92 | ## Acknowledgements 93 | - Original idea and initial testing by @Jondycz 94 | -------------------------------------------------------------------------------- /RemotePlayWhatever/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeList.txt : CMake project for RemotePlayWhatever, include source and define 2 | # project specific logic here. 3 | # 4 | cmake_minimum_required (VERSION 3.8) 5 | 6 | if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows") 7 | set(SYSTEM_OS "Win") 8 | elseif(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux") 9 | set(SYSTEM_OS "Linux") 10 | else() 11 | message(FATAL_ERROR "Unsupported platform!") 12 | endif() 13 | 14 | if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) 15 | set(SYSTEM_ARCH "64") 16 | else() 17 | set(SYSTEM_ARCH "32") 18 | endif() 19 | 20 | add_custom_target(OpenSteamAPI) 21 | set(OSW_ROOT "${CMAKE_CURRENT_LIST_DIR}/../open-steamworks") 22 | set(OSW_INCLUDE_PATH "${OSW_ROOT}/OpenSteamworks") 23 | set(OSW_LIB_ROOT "${OSW_ROOT}/OpenSteamAPI") 24 | if(${SYSTEM_OS} STREQUAL "Win") 25 | if(${SYSTEM_ARCH} STREQUAL "64") 26 | set(OSW_LIB_PATH "${OSW_LIB_ROOT}/lib/${SYSTEM_OS}${SYSTEM_ARCH}/OpenSteamAPI64.lib") 27 | set(OSW_DLL_PATH "${OSW_LIB_ROOT}/lib/${SYSTEM_OS}${SYSTEM_ARCH}/OpenSteamAPI64.dll") 28 | add_custom_command(TARGET OpenSteamAPI 29 | WORKING_DIRECTORY "${OSW_ROOT}" 30 | COMMAND msbuild /p:Platform=x64 /p:Configuration=Release 31 | VERBATIM 32 | ) 33 | else() 34 | set(OSW_LIB_PATH "${OSW_LIB_ROOT}/lib/${SYSTEM_OS}${SYSTEM_ARCH}/OpenSteamAPI.lib") 35 | set(OSW_DLL_PATH "${OSW_LIB_ROOT}/lib/${SYSTEM_OS}${SYSTEM_ARCH}/OpenSteamAPI.dll") 36 | add_custom_command(TARGET OpenSteamAPI 37 | WORKING_DIRECTORY "${OSW_ROOT}" 38 | COMMAND msbuild /p:Platform=Win32 /p:Configuration=Release 39 | VERBATIM 40 | ) 41 | endif() 42 | else() 43 | set(OSW_LIB_PATH "${OSW_LIB_ROOT}/lib/${SYSTEM_OS}${SYSTEM_ARCH}/OpenSteamAPI.a") 44 | add_custom_command(TARGET OpenSteamAPI 45 | PRE_BUILD 46 | WORKING_DIRECTORY "${OSW_LIB_ROOT}/src" 47 | COMMAND make 48 | VERBATIM 49 | ) 50 | endif() 51 | 52 | find_package(wxWidgets COMPONENTS core base adv) 53 | if(NOT wxWidgets_FOUND) 54 | message(FATAL_ERROR "wxWidgets not found!") 55 | endif() 56 | 57 | include(${wxWidgets_USE_FILE}) 58 | 59 | set(APPSRCs "RemotePlayWhatever.cpp" 60 | "SteamStuff.h" 61 | "SteamStuff.cpp" 62 | "RemoteApp.h" 63 | "RemoteApp.cpp" 64 | "RemotePlayInviteHandler.h" 65 | "RemotePlayInviteHandler.cpp" 66 | "QueueInviter.cpp" 67 | "QueueInviter.h" 68 | "FriendsListFrame.h" 69 | "FriendsListFrame.cpp" 70 | "ClickablePanel.h" 71 | "ClickablePanel.cpp" 72 | "FriendPanel.h" 73 | "FriendPanel.cpp" 74 | "wxSteamStuff.h" 75 | "wxSteamStuff.cpp" 76 | ) 77 | 78 | 79 | if(${SYSTEM_OS} STREQUAL "Win") 80 | add_executable(RemotePlayWhatever WIN32 ${APPSRCs} "appresource.rc") 81 | add_custom_command(TARGET RemotePlayWhatever POST_BUILD 82 | COMMAND ${CMAKE_COMMAND} -E copy ${OSW_DLL_PATH} $ 83 | ) 84 | else() 85 | add_executable(RemotePlayWhatever ${APPSRCs}) 86 | endif() 87 | add_dependencies(RemotePlayWhatever OpenSteamAPI) 88 | 89 | target_compile_definitions(RemotePlayWhatever PRIVATE STEAMWORKS_CLIENT_INTERFACES) 90 | target_include_directories(RemotePlayWhatever PUBLIC ${OSW_INCLUDE_PATH} ${wxWidgets_INCLUDE_DIRS}) 91 | target_link_libraries(RemotePlayWhatever ${OSW_LIB_PATH} ${wxWidgets_LIBRARIES}) 92 | if(${SYSTEM_OS} STREQUAL "Linux") 93 | target_link_libraries(RemotePlayWhatever ${CMAKE_DL_LIBS}) 94 | set_target_properties(RemotePlayWhatever PROPERTIES OUTPUT_NAME "remoteplaywhatever") 95 | install(TARGETS RemotePlayWhatever DESTINATION "bin") 96 | 97 | file(READ "/etc/issue" ISSUE) 98 | string(REGEX MATCH "Debian|Ubuntu" DISTRO ${ISSUE}) 99 | if(DISTRO MATCHES "Ubuntu" OR DISTRO MATCHES "Debian") 100 | set(CPACK_GENERATOR "DEB") 101 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Lets you force steam remote play together for any game") 102 | set(CPACK_PACKAGE_DESCRIPTION "Tiny app that lets you force steam remote play together for any game") 103 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "m4dEngi") 104 | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) 105 | include(CPack) 106 | endif() 107 | endif() 108 | 109 | -------------------------------------------------------------------------------- /RemotePlayWhatever/ClickablePanel.cpp: -------------------------------------------------------------------------------- 1 | #include "ClickablePanel.h" 2 | 3 | wxDEFINE_EVENT(BTN_PANEL_LEFT_CLICK, wxCommandEvent); 4 | 5 | ClickablePanel::ClickablePanel(wxWindow *parent, wxWindowID winID): 6 | wxPanel(parent, winID) 7 | { 8 | } 9 | 10 | ClickablePanel::~ClickablePanel() 11 | { 12 | } 13 | 14 | void ClickablePanel::RSetForegroundColour(const wxColour &colour) 15 | { 16 | wxWindowList kidz = GetChildren(); 17 | for(auto it = kidz.begin(); it != kidz.end(); ++it) 18 | { 19 | (*it)->SetForegroundColour(colour); 20 | } 21 | } 22 | 23 | void ClickablePanel::RSetBackgroundColour(const wxColour &colour) 24 | { 25 | wxWindowList kidz = GetChildren(); 26 | for(auto it = kidz.begin(); it != kidz.end(); ++it) 27 | { 28 | (*it)->SetBackgroundColour(colour); 29 | } 30 | } 31 | 32 | void ClickablePanel::RBindBaseEvents() 33 | { 34 | Bind( wxEVT_ENTER_WINDOW, &ClickablePanel::OnMouseEnter, this); 35 | Bind( wxEVT_LEAVE_WINDOW, &ClickablePanel::OnMouseLeave, this); 36 | Bind( wxEVT_LEFT_DOWN , &ClickablePanel::OnMouseLeftDown, this); 37 | Bind( wxEVT_LEFT_UP , &ClickablePanel::OnMouseLeftUp, this); 38 | 39 | wxWindowList kidz = GetChildren(); 40 | for(auto it = kidz.begin(); it != kidz.end(); ++it) 41 | { 42 | (*it)->Bind( wxEVT_LEFT_UP, &ClickablePanel::OnMouseLeftUp, this); 43 | (*it)->Bind( wxEVT_LEFT_DOWN, &ClickablePanel::OnMouseLeftDown, this); 44 | } 45 | } 46 | 47 | void ClickablePanel::OnMouseEnter(wxMouseEvent& event) 48 | { 49 | SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)); 50 | RSetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT)); 51 | Refresh(); 52 | } 53 | 54 | void ClickablePanel::OnMouseLeave(wxMouseEvent &event) 55 | { 56 | // check if we're actually leaving panel or just hovering over children 57 | wxPoint evtPoint = event.GetPosition(); 58 | wxSize parentSize = this->GetSize(); 59 | if( evtPoint.x > 0 && evtPoint.x < parentSize.x && 60 | evtPoint.y > 0 && evtPoint.y < parentSize.y 61 | ) 62 | { 63 | return; 64 | } 65 | 66 | SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); 67 | RSetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); 68 | Refresh(); 69 | } 70 | 71 | void ClickablePanel::OnMouseLeftDown(wxMouseEvent &event) 72 | { 73 | SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); 74 | Refresh(); 75 | } 76 | 77 | void ClickablePanel::OnMouseLeftUp(wxMouseEvent &event) 78 | { 79 | SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); 80 | RSetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); 81 | Refresh(); 82 | 83 | wxCommandEvent outEvt(BTN_PANEL_LEFT_CLICK, GetId()); 84 | outEvt.SetEventObject(this); 85 | ProcessWindowEvent(outEvt); 86 | } 87 | 88 | 89 | 90 | BtnPanel::BtnPanel(wxWindow *parent, wxWindowID winID, wxString label): 91 | ClickablePanel(parent, winID) 92 | { 93 | SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); 94 | 95 | wxBoxSizer* rootSizer = new wxBoxSizer( wxVERTICAL ); 96 | 97 | rootSizer->Add( 0, 8, 1, wxEXPAND, 0 ); 98 | 99 | m_label = new wxStaticText(this, wxID_ANY, label, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL); 100 | rootSizer->Add(m_label, 0, wxALL | wxEXPAND, 5 ); 101 | 102 | rootSizer->Add( 0, 8, 1, wxEXPAND, 0 ); 103 | 104 | SetSizer( rootSizer ); 105 | 106 | Layout(); 107 | 108 | RBindBaseEvents(); 109 | } 110 | 111 | BtnPanel::~BtnPanel() 112 | { 113 | 114 | } 115 | 116 | void BtnPanel::SetLabel(wxString &label) 117 | { 118 | m_label->SetLabel(label); 119 | } 120 | 121 | -------------------------------------------------------------------------------- /RemotePlayWhatever/ClickablePanel.h: -------------------------------------------------------------------------------- 1 | #ifndef CLICKABLEPANEL_H 2 | #define CLICKABLEPANEL_H 3 | #include 4 | 5 | wxDECLARE_EVENT(BTN_PANEL_LEFT_CLICK, wxCommandEvent); 6 | 7 | class ClickablePanel: public wxPanel 8 | { 9 | public: 10 | ClickablePanel(wxWindow* parent, wxWindowID winID); 11 | ~ClickablePanel(); 12 | 13 | protected: 14 | void RBindBaseEvents(); 15 | 16 | void OnMouseEnter(wxMouseEvent& event); 17 | void OnMouseLeave(wxMouseEvent& event); 18 | void OnMouseLeftDown(wxMouseEvent& event); 19 | void OnMouseLeftUp(wxMouseEvent& event); 20 | 21 | private: 22 | void RSetForegroundColour(const wxColour &colour); 23 | void RSetBackgroundColour(const wxColour &colour); 24 | }; 25 | 26 | class BtnPanel: public ClickablePanel 27 | { 28 | public: 29 | BtnPanel(wxWindow* parent, wxWindowID winID, wxString label); 30 | ~BtnPanel(); 31 | 32 | void SetLabel(wxString& label); 33 | 34 | private: 35 | wxStaticText* m_label; 36 | }; 37 | 38 | #endif // CLICKABLEPANEL_H 39 | -------------------------------------------------------------------------------- /RemotePlayWhatever/FriendPanel.cpp: -------------------------------------------------------------------------------- 1 | #include "wxSteamStuff.h" 2 | #include "FriendPanel.h" 3 | 4 | FriendPanel::FriendPanel(wxWindow* parent, wxWindowID winID, CSteamID friendID): 5 | ClickablePanel(parent, winID), 6 | m_steamID(friendID), 7 | m_personaNameLabel(nullptr), 8 | m_personaStateLabel(nullptr) 9 | { 10 | wxBoxSizer* rootSizer = new wxBoxSizer( wxHORIZONTAL ); 11 | 12 | SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); 13 | 14 | int av = GClientContext()->SteamFriends()->GetSmallFriendAvatar(friendID); 15 | if(av) 16 | { 17 | m_personaImg = new wxStaticBitmap( this, wxID_ANY, SteamImageToBitmap(av), wxDefaultPosition, wxSize( 32,32 ), 0 ); 18 | } 19 | else 20 | { 21 | m_personaImg = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), 0 ); 22 | } 23 | 24 | rootSizer->Add( m_personaImg, 0, wxALL, 10 ); 25 | 26 | wxBoxSizer* textSizer = new wxBoxSizer( wxVERTICAL ); 27 | 28 | textSizer->Add( 0, 0, 1, wxEXPAND, 5 ); 29 | wxString personaName; 30 | if(friendID.IsValid()) 31 | { 32 | personaName = wxString(GClientContext()->SteamFriends()->GetFriendPersonaName(friendID), wxConvUTF8); 33 | } 34 | m_personaNameLabel = new wxStaticText(this, wxID_ANY, personaName, wxDefaultPosition, wxDefaultSize, 0 ); 35 | textSizer->Add( m_personaNameLabel, 0, wxALL | wxEXPAND, 5 ); 36 | 37 | textSizer->Add( 0, 0, 1, wxEXPAND, 5 ); 38 | rootSizer->Add( textSizer, 1, wxALL|wxEXPAND, 5 ); 39 | 40 | SetSizer( rootSizer ); 41 | Layout(); 42 | 43 | RBindBaseEvents(); 44 | } 45 | 46 | FriendPanel::~FriendPanel() 47 | { 48 | } 49 | 50 | CSteamID FriendPanel::GetSteamID() 51 | { 52 | return m_steamID; 53 | } 54 | 55 | wxString FriendPanel::GetDisplayPersonaName() 56 | { 57 | return m_personaNameLabel->GetLabel(); 58 | } 59 | 60 | wxString FriendPanel::GetDisplayPersonaState() 61 | { 62 | return m_personaStateLabel->GetLabel(); 63 | } 64 | 65 | void FriendPanel::SetDisplayPersonaName(const wxString &name) 66 | { 67 | m_personaNameLabel->SetLabel(name); 68 | } 69 | 70 | void FriendPanel::SetDisaplayPersonaState(const wxString &state) 71 | { 72 | m_personaStateLabel->SetLabel(state); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /RemotePlayWhatever/FriendPanel.h: -------------------------------------------------------------------------------- 1 | #ifndef FRIENDPANEL_H 2 | #define FRIENDPANEL_H 3 | #include "ClickablePanel.h" 4 | #include "wxSteamStuff.h" 5 | 6 | class FriendPanel : public ClickablePanel 7 | { 8 | public: 9 | FriendPanel(wxWindow* parent, wxWindowID winID, CSteamID friendID); 10 | ~FriendPanel(); 11 | 12 | CSteamID GetSteamID(); 13 | 14 | wxString GetDisplayPersonaName(); 15 | wxString GetDisplayPersonaState(); 16 | 17 | void SetDisplayPersonaName(const wxString& name); 18 | void SetDisaplayPersonaState(const wxString& state); 19 | 20 | private: 21 | wxStaticBitmap* m_personaImg; 22 | wxStaticText* m_personaNameLabel; 23 | wxStaticText* m_personaStateLabel; 24 | 25 | CSteamID m_steamID; 26 | }; 27 | 28 | #endif // FRIENDPANEL_H 29 | -------------------------------------------------------------------------------- /RemotePlayWhatever/FriendsListFrame.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "FriendsListFrame.h" 5 | #include "FriendPanel.h" 6 | 7 | 8 | FriendsListFrame::FriendsListFrame(RemotePlayInviteHandler* handler): 9 | wxFrame(NULL, wxID_ANY, _("Remote Play Whatever"), wxPoint(50, 50), wxSize(275, 650)), 10 | m_remoteInviteResultCb(this, &FriendsListFrame::OnRemotePlayInviteResult), 11 | m_personaStateCb(this, &FriendsListFrame::OnPersonaStateChange) 12 | { 13 | SetSizeHints( wxDefaultSize, wxDefaultSize ); 14 | 15 | SetMinSize(wxSize(275, 300)); 16 | SetMaxSize(wxSize(350, -1)); 17 | 18 | m_pRemoteInvite = handler; 19 | 20 | wxBoxSizer* frameSizer = new wxBoxSizer( wxVERTICAL ); 21 | 22 | m_friendsListContainer = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL ); 23 | m_friendsListContainer->SetScrollRate( 5, 5 ); 24 | m_friendsListSizer = new wxBoxSizer( wxVERTICAL ); 25 | 26 | BtnPanel* guestBtn = new BtnPanel(m_friendsListContainer, rpwID_INVITE_GUEST, "Create guest invite link"); 27 | m_friendsListSizer->Add(guestBtn, 0, wxALL | wxEXPAND, 0); 28 | 29 | wxStaticText* flLabel = new wxStaticText(m_friendsListContainer, wxID_ANY, "or invite a friend", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL); 30 | m_friendsListSizer->Add(flLabel, 0, wxALL | wxEXPAND, 10); 31 | 32 | int cFriends = GClientContext()->SteamFriends()->GetFriendCount(k_EFriendFlagImmediate); 33 | for(int i = 0; i < cFriends; ++i) 34 | { 35 | CSteamID friendSteamID = GClientContext()->SteamFriends()->GetFriendByIndex(i, k_EFriendFlagImmediate); 36 | EPersonaState personaState = GClientContext()->SteamFriends()->GetFriendPersonaState(friendSteamID); 37 | if(personaState != k_EPersonaStateOffline && personaState != k_EPersonaStateInvisible) 38 | { 39 | AddFreiendPanel(friendSteamID); 40 | } 41 | } 42 | 43 | m_friendsListContainer->SetSizer( m_friendsListSizer ); 44 | m_friendsListContainer->Layout(); 45 | m_friendsListSizer->Fit( m_friendsListContainer ); 46 | frameSizer->Add( m_friendsListContainer, 1, wxEXPAND | wxALL, 0 ); 47 | 48 | SetSizer( frameSizer ); 49 | Layout(); 50 | 51 | Bind(BTN_PANEL_LEFT_CLICK, &FriendsListFrame::OnFriendPanelClick, this, rpwID_INVITE_FRIEND); 52 | Bind(BTN_PANEL_LEFT_CLICK, &FriendsListFrame::OnGuestPanelClick, this, rpwID_INVITE_GUEST); 53 | } 54 | 55 | void FriendsListFrame::AddFreiendPanel(CSteamID friendID) 56 | { 57 | FriendPanel* fp = new FriendPanel(m_friendsListContainer, rpwID_INVITE_FRIEND, friendID); 58 | m_friendsListSizer->Add(fp, 0, wxBOTTOM | wxEXPAND, 1); 59 | 60 | uint64 friendID64 = friendID.ConvertToUint64(); 61 | auto it = m_friendPanels.find(friendID64); 62 | if(it != m_friendPanels.end()) 63 | { 64 | m_friendsListContainer->RemoveChild((*it).second); 65 | (*it).second->Destroy(); 66 | } 67 | m_friendPanels[friendID.ConvertToUint64()] = fp; 68 | } 69 | 70 | void FriendsListFrame::RemoveFriendPanel(CSteamID friendID) 71 | { 72 | uint64 friendID64 = friendID.ConvertToUint64(); 73 | auto it = m_friendPanels.find(friendID64); 74 | if(it != m_friendPanels.end()) 75 | { 76 | m_friendsListContainer->RemoveChild((*it).second); 77 | (*it).second->Destroy(); 78 | m_friendPanels.erase(it); 79 | } 80 | } 81 | 82 | void FriendsListFrame::OnPersonaStateChange(PersonaStateChange_t* personaStateCb) 83 | { 84 | if(personaStateCb->m_ulSteamID == GClientContext()->SteamUser()->GetSteamID()) 85 | { 86 | return; 87 | } 88 | 89 | if(!(GClientContext()->SteamFriends()->GetFriendRelationship(personaStateCb->m_ulSteamID) & 90 | k_EFriendRelationshipFriend)) 91 | { 92 | return; 93 | } 94 | 95 | if(personaStateCb->m_nChangeFlags & k_EPersonaChangeGoneOffline) 96 | { 97 | RemoveFriendPanel(personaStateCb->m_ulSteamID); 98 | Layout(); 99 | } 100 | else if(personaStateCb->m_nChangeFlags & k_EPersonaChangeComeOnline) 101 | { 102 | AddFreiendPanel(personaStateCb->m_ulSteamID); 103 | Layout(); 104 | } 105 | } 106 | 107 | void FriendsListFrame::OnRemotePlayInviteResult(RemotePlayInviteResult_t* inviteResultCb) 108 | { 109 | if (inviteResultCb->m_eResult != k_ERemoteClientLaunchResultOK) 110 | { 111 | wxMessageBox( 112 | wxString::Format("Could not create remote play session! (Result:%d)", inviteResultCb->m_eResult), 113 | "Remote Play Whatever", 114 | wxOK | wxICON_ERROR 115 | ); 116 | } 117 | else 118 | { 119 | if(inviteResultCb->m_player.m_playerID.IsValid()) 120 | { 121 | wxMessageBox( 122 | "Invite sent", 123 | "Remote Play Whatever", 124 | wxOK | wxICON_INFORMATION 125 | ); 126 | } 127 | else 128 | { 129 | if(wxTheClipboard->Open()) 130 | { 131 | wxTheClipboard->SetData(new wxTextDataObject(inviteResultCb->m_szConnectURL)); 132 | wxMessageBox( 133 | "Guest invite link created and copied to clipboard", 134 | "Remote Play Whatever", 135 | wxOK | wxICON_INFORMATION 136 | ); 137 | wxTheClipboard->Flush(); 138 | wxTheClipboard->Close(); 139 | } 140 | } 141 | } 142 | } 143 | 144 | void FriendsListFrame::OnFriendPanelClick(wxCommandEvent &event) 145 | { 146 | if (!GClientContext()->SteamUser()->BLoggedOn() || !GetRunningGameID().IsValid()) 147 | { 148 | wxMessageBox 149 | ( 150 | "Could not detect game running. Start a game first!", 151 | "No game runnunig!", 152 | wxOK | wxICON_INFORMATION 153 | ); 154 | 155 | return; 156 | } 157 | 158 | FriendPanel* sender = (FriendPanel*)event.GetEventObject(); 159 | CSteamID invitee = sender->GetSteamID(); 160 | wxMessageDialog* dlg = new wxMessageDialog(this, "Send remote play invite to " + sender->GetDisplayPersonaName() + "?", "Confirm Remote Play Invite", wxOK | wxCANCEL); 161 | if(dlg->ShowModal() == wxID_OK) 162 | { 163 | m_pRemoteInvite->SendInvite(invitee); 164 | } 165 | delete dlg; 166 | } 167 | 168 | void FriendsListFrame::OnGuestPanelClick(wxCommandEvent &event) 169 | { 170 | if (!GClientContext()->SteamUser()->BLoggedOn() || !GetRunningGameID().IsValid()) 171 | { 172 | wxMessageBox 173 | ( 174 | "Could not detect game running. Start a game first!", 175 | "No game runnunig!", 176 | wxOK | wxICON_INFORMATION 177 | ); 178 | 179 | return; 180 | } 181 | 182 | wxMessageDialog* dlg = new wxMessageDialog(this, "Create guest invite link?", "Confirm Remote Play Invite", wxOK | wxCANCEL); 183 | if(dlg->ShowModal() == wxID_OK) 184 | { 185 | m_pRemoteInvite->SendInvite((uint64)0); 186 | } 187 | delete dlg; 188 | } 189 | 190 | -------------------------------------------------------------------------------- /RemotePlayWhatever/FriendsListFrame.h: -------------------------------------------------------------------------------- 1 | #ifndef FRIENDSLISTFRAME_H 2 | #define FRIENDSLISTFRAME_H 3 | #include 4 | #include 5 | #include "FriendPanel.h" 6 | #include "RemotePlayInviteHandler.h" 7 | 8 | enum ERPWEvtID 9 | { 10 | rpwID_INVITE_GUEST, 11 | rpwID_INVITE_FRIEND, 12 | }; 13 | 14 | class FriendsListFrame : public wxFrame 15 | { 16 | public: 17 | FriendsListFrame(RemotePlayInviteHandler* handler); 18 | 19 | private: 20 | void AddFreiendPanel(CSteamID friendID); 21 | void RemoveFriendPanel(CSteamID friendID); 22 | 23 | RemotePlayInviteHandler* m_pRemoteInvite; 24 | wxScrolledWindow* m_friendsListContainer; 25 | wxBoxSizer* m_friendsListSizer; 26 | 27 | std::map m_friendPanels; 28 | 29 | void OnFriendPanelClick(wxCommandEvent& event); 30 | void OnGuestPanelClick(wxCommandEvent& event); 31 | 32 | STEAM_CALLBACK(FriendsListFrame, OnRemotePlayInviteResult, RemotePlayInviteResult_t, m_remoteInviteResultCb); 33 | STEAM_CALLBACK(FriendsListFrame, OnPersonaStateChange, PersonaStateChange_t, m_personaStateCb); 34 | }; 35 | 36 | #endif // FRIENDSLISTFRAME_H 37 | -------------------------------------------------------------------------------- /RemotePlayWhatever/QueueInviter.cpp: -------------------------------------------------------------------------------- 1 | #include "QueueInviter.h" 2 | 3 | QueueInviter::QueueInviter(RemotePlayInviteHandler* handler, std::queue* que): 4 | m_handler(handler), 5 | m_running(false), 6 | m_inviteQueue(que), 7 | m_remoteInviteResultCb(this, &QueueInviter::OnRemotePlayInviteResult) 8 | { 9 | } 10 | 11 | QueueInviter::~QueueInviter() 12 | { 13 | } 14 | 15 | void QueueInviter::SendInvites() 16 | { 17 | if(m_running || m_inviteQueue->empty()) 18 | { 19 | return; 20 | } 21 | m_running = true; 22 | 23 | m_handler->SendInvite(m_inviteQueue->front()); 24 | } 25 | 26 | bool QueueInviter::Running() 27 | { 28 | return m_running; 29 | } 30 | 31 | void QueueInviter::OnRemotePlayInviteResult(RemotePlayInviteResult_t* inviteResultCb) 32 | { 33 | if( m_inviteQueue->empty() || 34 | inviteResultCb->m_player.m_playerID != m_inviteQueue->front() 35 | ) 36 | { 37 | return; 38 | } 39 | 40 | if(inviteResultCb->m_eResult == k_ERemoteClientLaunchResultOK) 41 | { 42 | std::cout << " - guestid : " << inviteResultCb->m_player.m_guestID <m_szConnectURL <pop(); 49 | 50 | if(m_inviteQueue->empty()) 51 | { 52 | m_running = false; 53 | return; 54 | } 55 | 56 | m_handler->SendInvite(m_inviteQueue->front()); 57 | } 58 | -------------------------------------------------------------------------------- /RemotePlayWhatever/QueueInviter.h: -------------------------------------------------------------------------------- 1 | #ifndef QUEUEINVITER_H 2 | #define QUEUEINVITER_H 3 | #include 4 | #include 5 | #include "SteamStuff.h" 6 | #include "RemotePlayInviteHandler.h" 7 | 8 | class QueueInviter 9 | { 10 | public: 11 | QueueInviter(RemotePlayInviteHandler* handler, std::queue* que); 12 | ~QueueInviter(); 13 | 14 | void SendInvites(); 15 | bool Running(); 16 | 17 | private: 18 | bool m_running; 19 | 20 | std::queue* m_inviteQueue; 21 | RemotePlayInviteHandler* m_handler; 22 | 23 | STEAM_CALLBACK(QueueInviter, OnRemotePlayInviteResult, RemotePlayInviteResult_t, m_remoteInviteResultCb); 24 | }; 25 | 26 | #endif // QUEUEINVITER_H 27 | -------------------------------------------------------------------------------- /RemotePlayWhatever/RemoteApp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "RemoteApp.h" 4 | #include "wxSteamStuff.h" 5 | #include "FriendsListFrame.h" 6 | 7 | static const wxCmdLineEntryDesc cmdLineDesc[] = 8 | { 9 | { wxCMD_LINE_SWITCH, "h", "help", "show this help message" }, 10 | { wxCMD_LINE_SWITCH, "v", "verbose", "verbose output" }, 11 | { wxCMD_LINE_OPTION, "a", "appid", "AppID for non-steam games", wxCMD_LINE_VAL_NUMBER }, 12 | { wxCMD_LINE_OPTION, "i", "invite", "Send remote play invites to provided SteamID64s ( use 0 for guest link )", wxCMD_LINE_VAL_STRING }, 13 | { wxCMD_LINE_OPTION, "g", "guestid", "Guest client id", wxCMD_LINE_VAL_NUMBER }, 14 | { wxCMD_LINE_OPTION, "c", "cancel", "Cancel invite for provided SteamID64 and GuestID", wxCMD_LINE_VAL_STRING }, 15 | { wxCMD_LINE_NONE } 16 | }; 17 | 18 | RemoteApp::RemoteApp(): 19 | m_inviteHandler(nullptr), 20 | m_oneshot(false), 21 | m_guestID(1), 22 | m_nonSteamID(0), 23 | m_inviteToCancel(-1) 24 | { 25 | } 26 | 27 | bool RemoteApp::OnInit() 28 | { 29 | if (!wxApp::OnInit()) 30 | return false; 31 | 32 | if (!GClientContext()->Init()) 33 | { 34 | #ifndef _WIN32 35 | if(!m_oneshot) 36 | #endif 37 | wxMessageBox 38 | ( 39 | "Could not initialize steam client library!", 40 | "Error", 41 | wxOK | wxICON_ERROR 42 | ); 43 | 44 | std::cout << "Error: Could not initialize steam client library!" << std::endl; 45 | 46 | return false; 47 | } 48 | 49 | return true; 50 | } 51 | 52 | int RemoteApp::OnRun() 53 | { 54 | m_inviteHandler = new RemotePlayInviteHandler(); 55 | m_inviteHandler->SetGuestID(m_guestID); 56 | m_inviteHandler->SetNonSteamAppID(m_nonSteamID); 57 | 58 | if(!m_oneshot) 59 | { 60 | m_callbackRunner.Start(200); 61 | 62 | m_friendsList = new FriendsListFrame(m_inviteHandler); 63 | m_friendsList->Show(true); 64 | 65 | return wxApp::OnRun(); 66 | } 67 | 68 | if(!m_inviteQue.empty() && 69 | GetRunningGameID().IsValid() && 70 | GClientContext()->SteamUser()->BLoggedOn() 71 | ) 72 | { 73 | QueueInviter qinviter(m_inviteHandler, &m_inviteQue); 74 | qinviter.SendInvites(); 75 | while(qinviter.Running()) 76 | { 77 | // look at me... i'm the main event loop now 78 | GClientContext()->RunCallbacks(); 79 | 80 | wxMilliSleep(200); 81 | } 82 | } 83 | 84 | if(m_inviteToCancel != -1) 85 | { 86 | m_inviteHandler->CancelInvite(m_inviteToCancel, m_guestID); 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | int RemoteApp::OnExit() 93 | { 94 | if (m_callbackRunner.IsRunning()) 95 | { 96 | m_callbackRunner.Stop(); 97 | } 98 | 99 | if(m_inviteHandler) 100 | { 101 | delete m_inviteHandler; 102 | } 103 | 104 | GClientContext()->Shutdown(); 105 | 106 | return 0; 107 | } 108 | 109 | bool RemoteApp::OnCmdLineParsed(wxCmdLineParser &parser) 110 | { 111 | if(parser.FoundSwitch("h")) 112 | { 113 | parser.Usage(); 114 | 115 | wxTheApp->Exit(); 116 | } 117 | 118 | long appID; 119 | if(parser.Found("a", &appID)) 120 | { 121 | m_nonSteamID = appID; 122 | } 123 | 124 | long guestID; 125 | if(parser.Found("g", &guestID)) 126 | { 127 | m_guestID = guestID; 128 | } 129 | 130 | wxString inviteeStr64; 131 | if(parser.Found("i", &inviteeStr64)) 132 | { 133 | m_oneshot = true; 134 | size_t first = 0, last = 0; 135 | while(last != wxString::npos) 136 | { 137 | last = inviteeStr64.find(",", first); 138 | uint64 invitee = 0; 139 | if(inviteeStr64.substr(first, last - first).ToULongLong(&invitee)) 140 | { 141 | m_inviteQue.push(invitee); 142 | } 143 | first = last + 1; 144 | } 145 | } 146 | else if (parser.Found("c", &inviteeStr64)) 147 | { 148 | m_oneshot = true; 149 | inviteeStr64.ToULongLong(&m_inviteToCancel); 150 | } 151 | 152 | return wxApp::OnCmdLineParsed(parser); 153 | } 154 | 155 | void RemoteApp::OnInitCmdLine(wxCmdLineParser &parser) 156 | { 157 | parser.SetDesc(cmdLineDesc); 158 | } 159 | 160 | // -- 161 | 162 | void RemoteAppCallbackRunner::Notify() 163 | { 164 | GClientContext()->RunCallbacks(); 165 | } 166 | 167 | 168 | -------------------------------------------------------------------------------- /RemotePlayWhatever/RemoteApp.h: -------------------------------------------------------------------------------- 1 | #ifndef REMOTEAPP_H 2 | #define REMOTEAPP_H 3 | #include 4 | #include 5 | #include "SteamStuff.h" 6 | #include "RemotePlayInviteHandler.h" 7 | #include "QueueInviter.h" 8 | 9 | class OneShotInvite 10 | { 11 | public: 12 | OneShotInvite(CSteamID invitee, RemotePlayInviteHandler* handler); 13 | void Send(); 14 | 15 | private: 16 | CSteamID m_invitee; 17 | RemotePlayInviteHandler* m_handler; 18 | 19 | STEAM_CALLBACK(OneShotInvite, OnRemotePlayInviteResult, RemotePlayInviteResult_t, m_remoteInviteResultCb); 20 | }; 21 | 22 | class RemoteAppCallbackRunner : public wxTimer 23 | { 24 | public: 25 | virtual void Notify() override; 26 | }; 27 | 28 | class RemoteApp : public wxApp 29 | { 30 | public: 31 | RemoteApp(); 32 | 33 | virtual bool OnInit() override; 34 | virtual int OnRun() override; 35 | virtual int OnExit() override; 36 | virtual bool OnCmdLineParsed(wxCmdLineParser& parser) override; 37 | virtual void OnInitCmdLine(wxCmdLineParser& parser) override; 38 | 39 | private: 40 | bool m_oneshot; 41 | 42 | 43 | wxFrame* m_friendsList; 44 | RemoteAppCallbackRunner m_callbackRunner; 45 | 46 | std::queue m_inviteQue; 47 | AppId_t m_nonSteamID; 48 | uint64 m_guestID; 49 | uint64 m_inviteToCancel; 50 | 51 | RemotePlayInviteHandler* m_inviteHandler; 52 | }; 53 | 54 | #endif // !REMOTEAPP_H 55 | -------------------------------------------------------------------------------- /RemotePlayWhatever/RemotePlayInviteHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "SteamStuff.h" 2 | #include "RemotePlayInviteHandler.h" 3 | 4 | RemotePlayInviteHandler::RemotePlayInviteHandler() : 5 | m_enabledDesktopStreaming(false), 6 | m_remoteGuestID(1), 7 | m_nonsteamAppID(0), 8 | m_remoteInviteResultCb(this, &RemotePlayInviteHandler::OnRemotePlayInviteResult), 9 | m_remoteStopCb(this, &RemotePlayInviteHandler::OnRemotePlayStop) 10 | { 11 | } 12 | 13 | void RemotePlayInviteHandler::SendInvite(CSteamID invitee) 14 | { 15 | CGameID gameID = GetRunningGameID(); 16 | 17 | if (!gameID.IsValid()) 18 | { 19 | return; 20 | } 21 | 22 | RemotePlayPlayer_t rppInvitee = { invitee, m_remoteGuestID, 0, 0, 0 }; 23 | ++m_remoteGuestID; 24 | 25 | if (gameID.IsSteamApp() && gameID.AppID() != m_nonsteamAppID) 26 | { 27 | GClientContext()->RemoteClientManager()->BCreateRemotePlayInviteAndSession(rppInvitee, gameID.AppID()); 28 | } 29 | else 30 | { 31 | GClientContext()->RemoteClientManager()->SetStreamingDesktopToRemotePlayTogetherEnabled(true); 32 | 33 | m_enabledDesktopStreaming = true; 34 | 35 | GClientContext()->RemoteClientManager()->BCreateRemotePlayInviteAndSession(rppInvitee, m_nonsteamAppID); 36 | } 37 | } 38 | 39 | void RemotePlayInviteHandler::CancelInvite(CSteamID invitee, uint64 guestID) 40 | { 41 | if(GClientContext()->RemoteClientManager()->BIsStreamingSessionActive()) 42 | { 43 | RemotePlayPlayer_t rppInvitee = { invitee, guestID, 0, 0, 0 }; 44 | GClientContext()->RemoteClientManager()->CancelRemotePlayInviteAndSession(rppInvitee); 45 | } 46 | } 47 | 48 | void RemotePlayInviteHandler::SetNonSteamAppID(AppId_t appID) 49 | { 50 | m_nonsteamAppID = appID; 51 | } 52 | 53 | void RemotePlayInviteHandler::SetGuestID(uint64 guestID) 54 | { 55 | m_remoteGuestID = guestID; 56 | } 57 | 58 | void RemotePlayInviteHandler::OnRemotePlayInviteResult(RemotePlayInviteResult_t* inviteResultCb) 59 | { 60 | if (inviteResultCb->m_eResult == k_ERemoteClientLaunchResultOK) 61 | { 62 | if (inviteResultCb->m_player.m_playerID.IsValid()) 63 | { 64 | char* buf = new char[1280]; 65 | sprintf(buf, "Follow this link to join remote game: %s", inviteResultCb->m_szConnectURL); 66 | GClientContext()->SteamFriends()->ReplyToFriendMessage(inviteResultCb->m_player.m_playerID, buf); 67 | delete[] buf; 68 | } 69 | GClientContext()->RemoteClientManager()->ShowRemotePlayTogetherUI(GetRunningGameID().AppID()); 70 | } 71 | } 72 | 73 | void RemotePlayInviteHandler::OnRemotePlayStop(RemoteClientStopStreamSession_t* streamStopCb) 74 | { 75 | if (!GClientContext()->RemoteClientManager()->BIsStreamingSessionActive() && 76 | m_enabledDesktopStreaming 77 | ) 78 | { 79 | GClientContext()->RemoteClientManager()->SetStreamingDesktopToRemotePlayTogetherEnabled(false); 80 | m_remoteGuestID = 1; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /RemotePlayWhatever/RemotePlayInviteHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef REMOTEPLAYINVITEHANDLER_H 2 | #define REMOTEPLAYINVITEHANDLER_H 3 | 4 | #include 5 | 6 | class RemotePlayInviteHandler 7 | { 8 | public: 9 | RemotePlayInviteHandler(); 10 | virtual ~RemotePlayInviteHandler() {} 11 | 12 | void SendInvite(CSteamID invitee); 13 | void CancelInvite(CSteamID invitee, uint64 guestID); 14 | 15 | void SetNonSteamAppID(AppId_t appID); 16 | void SetGuestID(uint64 guestID); 17 | 18 | private: 19 | bool m_enabledDesktopStreaming; 20 | uint64 m_remoteGuestID; 21 | AppId_t m_nonsteamAppID; 22 | 23 | STEAM_CALLBACK(RemotePlayInviteHandler, OnRemotePlayStop, RemoteClientStopStreamSession_t, m_remoteStopCb); 24 | STEAM_CALLBACK(RemotePlayInviteHandler, OnRemotePlayInviteResult, RemotePlayInviteResult_t, m_remoteInviteResultCb); 25 | }; 26 | 27 | #endif // REMOTEPLAYINVITEHANDLER_H 28 | -------------------------------------------------------------------------------- /RemotePlayWhatever/RemotePlayWhatever.cpp: -------------------------------------------------------------------------------- 1 | #include "RemoteApp.h" 2 | 3 | wxIMPLEMENT_APP(RemoteApp); 4 | -------------------------------------------------------------------------------- /RemotePlayWhatever/RemotePlayWhatever.h: -------------------------------------------------------------------------------- 1 | // RemotePlayWhatever.h : Include file for standard system include files, 2 | // or project specific include files. 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | // TODO: Reference additional headers your program requires here. 9 | -------------------------------------------------------------------------------- /RemotePlayWhatever/SteamStuff.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SteamStuff.h" 3 | 4 | // steam client context 5 | 6 | ClientContext::ClientContext(): 7 | m_hPipe(0), 8 | m_hUser(0), 9 | m_pSteamUser(nullptr), 10 | m_pSteamFriends(nullptr), 11 | m_pSteamClient(nullptr), 12 | m_pClientEngine(nullptr), 13 | m_pClientRemoteManager(nullptr), 14 | m_ShuttingDown(false) 15 | { 16 | } 17 | 18 | ClientContext::~ClientContext() 19 | { 20 | } 21 | 22 | bool ClientContext::Init() 23 | { 24 | if(m_Initialized) 25 | { 26 | return true; 27 | } 28 | 29 | if (!OpenAPI_LoadLibrary()) 30 | { 31 | return false; 32 | } 33 | 34 | m_pSteamClient = (ISteamClient019*)SteamInternal_CreateInterface(STEAMCLIENT_INTERFACE_VERSION_019); 35 | if (!m_pSteamClient) 36 | { 37 | return false; 38 | } 39 | 40 | m_hPipe = m_pSteamClient->CreateSteamPipe(); 41 | if (!m_hPipe) 42 | { 43 | return false; 44 | } 45 | 46 | m_hUser = m_pSteamClient->ConnectToGlobalUser(m_hPipe); 47 | if (!m_hUser) 48 | { 49 | return false; 50 | } 51 | 52 | m_pSteamUser = (ISteamUser019*)m_pSteamClient->GetISteamUser(m_hUser, m_hPipe, STEAMUSER_INTERFACE_VERSION_019); 53 | if (!m_pSteamUser) 54 | { 55 | return false; 56 | } 57 | 58 | m_pSteamFriends = (ISteamFriends015*)m_pSteamClient->GetISteamFriends(m_hUser, m_hPipe, STEAMFRIENDS_INTERFACE_VERSION_015); 59 | if (!m_pSteamFriends) 60 | { 61 | return false; 62 | } 63 | 64 | m_pSteamUtils = (ISteamUtils009*)m_pSteamClient->GetISteamUtils(m_hPipe, STEAMUTILS_INTERFACE_VERSION_009); 65 | if(!m_pSteamUtils) 66 | { 67 | return false; 68 | } 69 | 70 | m_pClientEngine = (IClientEngine*)SteamInternal_CreateInterface(CLIENTENGINE_INTERFACE_VERSION); 71 | if (!m_pClientEngine) 72 | { 73 | return false; 74 | } 75 | 76 | m_pClientRemoteManager = (IClientRemoteClientManager*)m_pClientEngine->GetIClientRemoteClientManager(m_hPipe); 77 | if (!m_pClientRemoteManager) 78 | { 79 | return false; 80 | } 81 | 82 | return m_Initialized = true; 83 | } 84 | 85 | void ClientContext::Shutdown() 86 | { 87 | if(m_ShuttingDown) 88 | { 89 | return; 90 | } 91 | 92 | m_ShuttingDown = true; 93 | 94 | if (m_hPipe) 95 | { 96 | if (m_hUser) 97 | { 98 | m_pSteamClient->ReleaseUser(m_hPipe, m_hUser); 99 | } 100 | if(m_pSteamClient->BReleaseSteamPipe(m_hPipe)) 101 | { 102 | m_pSteamClient->BShutdownIfAllPipesClosed(); 103 | } 104 | } 105 | } 106 | 107 | ISteamUser019* ClientContext::SteamUser() 108 | { 109 | return m_pSteamUser; 110 | } 111 | 112 | ISteamFriends015* ClientContext::SteamFriends() 113 | { 114 | return m_pSteamFriends; 115 | } 116 | 117 | ISteamUtils009 *ClientContext::SteamUtils() 118 | { 119 | return m_pSteamUtils; 120 | } 121 | 122 | void ClientContext::RunCallbacks() 123 | { 124 | if(!m_ShuttingDown) 125 | { 126 | Steam_RunCallbacks(m_hPipe, false); 127 | } 128 | } 129 | 130 | IClientRemoteClientManager* ClientContext::RemoteClientManager() 131 | { 132 | return m_pClientRemoteManager; 133 | } 134 | 135 | // helper functions 136 | 137 | ClientContext* GClientContext() 138 | { 139 | static ClientContext ctx; 140 | return &ctx; 141 | } 142 | 143 | CGameID GetRunningGameID() 144 | { 145 | FriendGameInfo_t gameInfo; 146 | if(GClientContext()->SteamFriends()->GetFriendGamePlayed(GClientContext()->SteamUser()->GetSteamID(), &gameInfo)) 147 | { 148 | return gameInfo.m_gameID; 149 | } 150 | 151 | return CGameID(); 152 | } 153 | 154 | 155 | -------------------------------------------------------------------------------- /RemotePlayWhatever/SteamStuff.h: -------------------------------------------------------------------------------- 1 | #ifndef STEAMSTUFF_H 2 | #define STEAMSTUFF_H 3 | 4 | #include 5 | 6 | class ClientContext 7 | { 8 | public: 9 | ClientContext(); 10 | ~ClientContext(); 11 | 12 | ISteamUser019* SteamUser(); 13 | ISteamFriends015* SteamFriends(); 14 | ISteamUtils009* SteamUtils(); 15 | 16 | IClientRemoteClientManager* RemoteClientManager(); 17 | 18 | bool Init(); 19 | void Shutdown(); 20 | void RunCallbacks(); 21 | 22 | private: 23 | HSteamPipe m_hPipe; 24 | HSteamUser m_hUser; 25 | 26 | ISteamClient019* m_pSteamClient; 27 | ISteamUser019* m_pSteamUser; 28 | ISteamFriends015* m_pSteamFriends; 29 | ISteamUtils009* m_pSteamUtils; 30 | 31 | IClientEngine* m_pClientEngine; 32 | IClientRemoteClientManager* m_pClientRemoteManager; 33 | 34 | bool m_ShuttingDown; 35 | bool m_Initialized; 36 | }; 37 | 38 | ClientContext* GClientContext(); 39 | CGameID GetRunningGameID(); 40 | 41 | #endif // !STEAMSTUFF_H 42 | -------------------------------------------------------------------------------- /RemotePlayWhatever/appicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m4dEngi/RemotePlayWhatever/bb549888e1d5d22db133b2e18dfc831dd6968027/RemotePlayWhatever/appicon.ico -------------------------------------------------------------------------------- /RemotePlayWhatever/appicon.xpm: -------------------------------------------------------------------------------- 1 | /* XPM */ 2 | static const char * appicon_xpm[] = { 3 | "128 128 852 2", 4 | " c None", 5 | ". c #000000", 6 | "+ c #000101", 7 | "@ c #000102", 8 | "# c #000204", 9 | "$ c #000205", 10 | "% c #000307", 11 | "& c #000408", 12 | "* c #00050A", 13 | "= c #00050C", 14 | "- c #00060E", 15 | "; c #000610", 16 | "> c #000712", 17 | ", c #000814", 18 | "' c #000916", 19 | ") c #000A18", 20 | "! c #000B1A", 21 | "~ c #000C1C", 22 | "{ c #000D1E", 23 | "] c #000E20", 24 | "^ c #000F22", 25 | "/ c #001024", 26 | "( c #001126", 27 | "_ c #00152C", 28 | ": c #006F8E", 29 | "< c #008FB3", 30 | "[ c #008FB2", 31 | "} c #006C87", 32 | "| c #000407", 33 | "1 c #0C0200", 34 | "2 c #8D3600", 35 | "3 c #B34600", 36 | "4 c #8C3600", 37 | "5 c #290E00", 38 | "6 c #240C00", 39 | "7 c #220C00", 40 | "8 c #200A00", 41 | "9 c #1E0A00", 42 | "0 c #1C0900", 43 | "a c #1A0800", 44 | "b c #180800", 45 | "c c #160700", 46 | "d c #140600", 47 | "e c #120600", 48 | "f c #100500", 49 | "g c #0E0500", 50 | "h c #0C0400", 51 | "i c #0A0400", 52 | "j c #080300", 53 | "k c #060200", 54 | "l c #050200", 55 | "m c #040100", 56 | "n c #020100", 57 | "o c #010000", 58 | "p c #000305", 59 | "q c #00050B", 60 | "r c #00070E", 61 | "s c #000810", 62 | "t c #000913", 63 | "u c #000B16", 64 | "v c #000C19", 65 | "w c #000D1C", 66 | "x c #000F1E", 67 | "y c #001021", 68 | "z c #001224", 69 | "A c #001327", 70 | "B c #00152A", 71 | "C c #00162D", 72 | "D c #00172F", 73 | "E c #001933", 74 | "F c #001A35", 75 | "G c #001B38", 76 | "H c #001D3B", 77 | "I c #002343", 78 | "J c #00A0CB", 79 | "K c #00CEFF", 80 | "L c #00CEFE", 81 | "M c #009EC4", 82 | "N c #000A0F", 83 | "O c #160400", 84 | "P c #C95000", 85 | "Q c #FF6600", 86 | "R c #3F1900", 87 | "S c #381600", 88 | "T c #351500", 89 | "U c #321400", 90 | "V c #2F1300", 91 | "W c #2C1200", 92 | "X c #291000", 93 | "Y c #270F00", 94 | "Z c #230E00", 95 | "` c #210D00", 96 | " . c #1E0C00", 97 | ".. c #1B0B00", 98 | "+. c #180A00", 99 | "@. c #160800", 100 | "#. c #130700", 101 | "$. c #100600", 102 | "%. c #0D0500", 103 | "&. c #070300", 104 | "*. c #040200", 105 | "=. c #000E1C", 106 | "-. c #000F1F", 107 | ";. c #001122", 108 | ">. c #001730", 109 | ",. c #001A36", 110 | "'. c #001C38", 111 | "). c #00A1CB", 112 | "!. c #CA5000", 113 | "~. c #381700", 114 | "{. c #301300", 115 | "]. c #2D1200", 116 | "^. c #2A1100", 117 | "/. c #240E00", 118 | "(. c #1D0D02", 119 | "_. c #1E1207", 120 | ":. c #211710", 121 | "<. c #231B15", 122 | "[. c #201A15", 123 | "}. c #1C1611", 124 | "|. c #140E0A", 125 | "1. c #090401", 126 | "2. c #2E1A0D", 127 | "3. c #413229", 128 | "4. c #65554B", 129 | "5. c #918379", 130 | "6. c #B1A39A", 131 | "7. c #B7AAA2", 132 | "8. c #BEB2AA", 133 | "9. c #C2B7B0", 134 | "0. c #C0B8B2", 135 | "a. c #BCB6B0", 136 | "b. c #B6B0AD", 137 | "c. c #AEABA8", 138 | "d. c #92908E", 139 | "e. c #595858", 140 | "f. c #313131", 141 | "g. c #151515", 142 | "h. c #341A08", 143 | "i. c #4F3B2F", 144 | "j. c #978376", 145 | "k. c #BFAA9C", 146 | "l. c #E1CDBF", 147 | "m. c #EBD8CA", 148 | "n. c #ECDACE", 149 | "o. c #EEDED3", 150 | "p. c #EEE0D6", 151 | "q. c #EEE1D8", 152 | "r. c #EDE2DA", 153 | "s. c #EDE4DD", 154 | "t. c #EDE5E0", 155 | "u. c #EDE7E3", 156 | "v. c #ECE8E5", 157 | "w. c #EAE8E6", 158 | "x. c #E8E7E7", 159 | "y. c #DFDFDF", 160 | "z. c #BBBBBB", 161 | "A. c #8B8B8B", 162 | "B. c #3D3D3D", 163 | "C. c #0F0F0F", 164 | "D. c #3B1E0C", 165 | "E. c #6D5547", 166 | "F. c #BAA190", 167 | "G. c #E3C9B7", 168 | "H. c #EDD5C4", 169 | "I. c #EFD8C8", 170 | "J. c #EFDACB", 171 | "K. c #EEDBCE", 172 | "L. c #EEDCD0", 173 | "M. c #EDE8E5", 174 | "N. c #ECEAE8", 175 | "O. c #ECEBEA", 176 | "P. c #ECECEC", 177 | "Q. c #EAEAEA", 178 | "R. c #E2E2E2", 179 | "S. c #B2B2B2", 180 | "T. c #5C5C5C", 181 | "U. c #161616", 182 | "V. c #411C04", 183 | "W. c #6A4F3F", 184 | "X. c #BEA28F", 185 | "Y. c #EACCB8", 186 | "Z. c #F0D3C0", 187 | "`. c #EFD5C3", 188 | " + c #EFD6C5", 189 | ".+ c #E7E7E7", 190 | "++ c #B8B8B8", 191 | "@+ c #535353", 192 | "#+ c #0A0A0A", 193 | "$+ c #CD5615", 194 | "%+ c #A68673", 195 | "&+ c #E6C5AF", 196 | "*+ c #F0D0BB", 197 | "=+ c #F0D2BE", 198 | "-+ c #9F9F9F", 199 | ";+ c #2C2C2C", 200 | ">+ c #F68C5A", 201 | ",+ c #EFCAB2", 202 | "'+ c #F0CFB8", 203 | ")+ c #C8C8C8", 204 | "!+ c #575757", 205 | "~+ c #030303", 206 | "{+ c #FA915F", 207 | "]+ c #F0CBB3", 208 | "^+ c #DBDBDB", 209 | "/+ c #767676", 210 | "(+ c #080808", 211 | "_+ c #E4E4E4", 212 | ":+ c #878787", 213 | "<+ c #EDDDD2", 214 | "[+ c #EBDDD3", 215 | "}+ c #EADDD5", 216 | "|+ c #E9DED6", 217 | "1+ c #E9E0DA", 218 | "2+ c #E9E2DC", 219 | "3+ c #EAE4E0", 220 | "4+ c #E5E5E5", 221 | "5+ c #848484", 222 | "6+ c #070707", 223 | "7+ c #EDD8CA", 224 | "8+ c #E3D0C3", 225 | "9+ c #C0AFA4", 226 | "0+ c #A79A91", 227 | "a+ c #7B6F67", 228 | "b+ c #5D534D", 229 | "c+ c #4E4540", 230 | "d+ c #4C4641", 231 | "e+ c #57514D", 232 | "f+ c #75706D", 233 | "g+ c #A09D9A", 234 | "h+ c #B9B7B5", 235 | "i+ c #DEDDDC", 236 | "j+ c #E3E3E3", 237 | "k+ c #787878", 238 | "l+ c #EFD4C2", 239 | "m+ c #ECD3C3", 240 | "n+ c #CCB6A7", 241 | "o+ c #907F74", 242 | "p+ c #44362E", 243 | "q+ c #281910", 244 | "r+ c #1C0C00", 245 | "s+ c #160900", 246 | "t+ c #080401", 247 | "u+ c #141211", 248 | "v+ c #353535", 249 | "w+ c #818181", 250 | "x+ c #C4C4C4", 251 | "y+ c #E8E8E8", 252 | "z+ c #D9D9D9", 253 | "A+ c #525252", 254 | "B+ c #EFD2BF", 255 | "C+ c #D5BCAB", 256 | "D+ c #857164", 257 | "E+ c #37241A", 258 | "F+ c #240F00", 259 | "G+ c #010101", 260 | "H+ c #1F1F1F", 261 | "I+ c #CDCDCD", 262 | "J+ c #EBEBEB", 263 | "K+ c #C9C9C9", 264 | "L+ c #2A2A2A", 265 | "M+ c #ECCEBA", 266 | "N+ c #B19787", 267 | "O+ c #483327", 268 | "P+ c #2A1101", 269 | "Q+ c #2E2E2E", 270 | "R+ c #A2A2A2", 271 | "S+ c #999999", 272 | "T+ c #F0CEB8", 273 | "U+ c #E9C9B4", 274 | "V+ c #957B6B", 275 | "W+ c #371D0E", 276 | "X+ c #210E00", 277 | "Y+ c #241409", 278 | "Z+ c #382E28", 279 | "`+ c #594E47", 280 | " @ c #7E746D", 281 | ".@ c #918882", 282 | "+@ c #918984", 283 | "@@ c #7D7772", 284 | "#@ c #56514E", 285 | "$@ c #312F2D", 286 | "%@ c #110E0C", 287 | "&@ c #101010", 288 | "*@ c #838383", 289 | "=@ c #E1E1E1", 290 | "-@ c #555555", 291 | ";@ c #E9C7B1", 292 | ">@ c #8D7363", 293 | ",@ c #351805", 294 | "'@ c #271000", 295 | ")@ c #301F14", 296 | "!@ c #6F6157", 297 | "~@ c #B7A69C", 298 | "{@ c #DDCDC2", 299 | "]@ c #EADCD2", 300 | "^@ c #EBDED6", 301 | "/@ c #EBE0D8", 302 | "(@ c #EBE2DC", 303 | "_@ c #EAE3DE", 304 | ":@ c #E9E3DF", 305 | "<@ c #DCD8D6", 306 | "[@ c #B3B1AF", 307 | "}@ c #696868", 308 | "|@ c #1C1C1C", 309 | "1@ c #050505", 310 | "2@ c #797979", 311 | "3@ c #B5B5B5", 312 | "4@ c #131313", 313 | "5@ c #EDC8B0", 314 | "6@ c #997C6A", 315 | "7@ c #381905", 316 | "8@ c #2B1303", 317 | "9@ c #615046", 318 | "0@ c #C2AEA1", 319 | "a@ c #EAD7CA", 320 | "b@ c #EEDBCF", 321 | "c@ c #ECE9E7", 322 | "d@ c #E8E7E6", 323 | "e@ c #BFBFBF", 324 | "f@ c #5A5A5A", 325 | "g@ c #060606", 326 | "h@ c #828282", 327 | "i@ c #E6E6E6", 328 | "j@ c #F9905D", 329 | "k@ c #B7957F", 330 | "l@ c #3F200E", 331 | "m@ c #321909", 332 | "n@ c #8D796D", 333 | "o@ c #E2CBBC", 334 | "p@ c #E0E0E0", 335 | "q@ c #898989", 336 | "r@ c #111111", 337 | "s@ c #B0B0B0", 338 | "t@ c #0C0C0C", 339 | "u@ c #E97B44", 340 | "v@ c #57341F", 341 | "w@ c #998375", 342 | "x@ c #EAD1C1", 343 | "y@ c #949494", 344 | "z@ c #303030", 345 | "A@ c #CECECE", 346 | "B@ c #DEDEDE", 347 | "C@ c #393939", 348 | "D@ c #CB5205", 349 | "E@ c #401A00", 350 | "F@ c #341602", 351 | "G@ c #8D7769", 352 | "H@ c #EAD0BE", 353 | "I@ c #E9E9E9", 354 | "J@ c #351600", 355 | "K@ c #634C3E", 356 | "L@ c #E2C6B3", 357 | "M@ c #565656", 358 | "N@ c #202020", 359 | "O@ c #C5C5C5", 360 | "P@ c #B7B7B7", 361 | "Q@ c #3C200F", 362 | "R@ c #C0A593", 363 | "S@ c #BDBDBD", 364 | "T@ c #1A1A1A", 365 | "U@ c #888888", 366 | "V@ c #DCDCDC", 367 | "W@ c #6F5546", 368 | "X@ c #EBCDB9", 369 | "Y@ c #646464", 370 | "Z@ c #383838", 371 | "`@ c #3A1A04", 372 | " # c #B59A88", 373 | ".# c #F0D1BD", 374 | "+# c #0B0B0B", 375 | "@# c #BCBCBC", 376 | "## c #472B1D", 377 | "$# c #DABBA6", 378 | "%# c #D8D8D8", 379 | "&# c #A6A6A6", 380 | "*# c #ABABAB", 381 | "=# c #5F4333", 382 | "-# c #ECCDB7", 383 | ";# c #4A4A4A", 384 | "># c #B1B1B1", 385 | ",# c #7A5E4C", 386 | "'# c #EDCEB8", 387 | ")# c #6F6F6F", 388 | "!# c #5B5B5B", 389 | "~# c #896D5B", 390 | "{# c #EECEB9", 391 | "]# c #858585", 392 | "^# c #4B4B4B", 393 | "/# c #886C5A", 394 | "(# c #4E4E4E", 395 | "_# c #B9B9B9", 396 | ":# c #121212", 397 | "<# c #785B4A", 398 | "[# c #6B6B6B", 399 | "}# c #5B3F30", 400 | "|# c #ECCCB7", 401 | "1# c #474747", 402 | "2# c #7F7F7F", 403 | "3# c #45291A", 404 | "4# c #D5B7A2", 405 | "5# c #D4D4D4", 406 | "6# c #292929", 407 | "7# c #020202", 408 | "8# c #A8A8A8", 409 | "9# c #A7A7A7", 410 | "0# c #3A1903", 411 | "a# c #AF9483", 412 | "b# c #EFD1BD", 413 | "c# c #ACACAC", 414 | "d# c #181818", 415 | "e# c #BEBEBE", 416 | "f# c #674E3F", 417 | "g# c #E9CBB7", 418 | "h# c #585858", 419 | "i# c #3F3F3F", 420 | "j# c #4C4C4C", 421 | "k# c #3A1D0A", 422 | "l# c #B89C8B", 423 | "m# c #EFD3C0", 424 | "n# c #B4B4B4", 425 | "o# c #141414", 426 | "p# c #8F8F8F", 427 | "q# c #573F32", 428 | "r# c #DDC1AF", 429 | "s# c #484848", 430 | "t# c #272727", 431 | "u# c #0E0E0E", 432 | "v# c #CC5308", 433 | "w# c #401A01", 434 | "x# c #331501", 435 | "y# c #806A5D", 436 | "z# c #E7CDBB", 437 | "A# c #7A7A7A", 438 | "B# c #7C7C7C", 439 | "C# c #ED7F4A", 440 | "D# c #5F3D29", 441 | "E# c #321704", 442 | "F# c #8C776A", 443 | "G# c #E6CEBD", 444 | "H# c #EFD7C8", 445 | "I# c #868686", 446 | "J# c #090909", 447 | "K# c #343434", 448 | "L# c #F9905E", 449 | "M# c #C29F89", 450 | "N# c #432616", 451 | "O# c #2F1604", 452 | "P# c #7E6B5F", 453 | "Q# c #DAC4B5", 454 | "R# c #EED9CB", 455 | "S# c #777777", 456 | "T# c #EEC9B1", 457 | "U# c #A48774", 458 | "V# c #3A1D09", 459 | "W# c #2A1201", 460 | "X# c #4F3E34", 461 | "Y# c #B2A094", 462 | "Z# c #E6D3C6", 463 | "`# c #EDDBCF", 464 | " $ c #EBE9E7", 465 | ".$ c #E4E3E3", 466 | "+$ c #AFAFAF", 467 | "@$ c #424242", 468 | "#$ c #919191", 469 | "$$ c #4D4D4D", 470 | "%$ c #ECCBB4", 471 | "&$ c #9A7F6E", 472 | "*$ c #381C0A", 473 | "=$ c #2A170B", 474 | "-$ c #594A42", 475 | ";$ c #A8998F", 476 | ">$ c #CDBEB4", 477 | ",$ c #E8DAD0", 478 | "'$ c #EADED5", 479 | ")$ c #EADFD7", 480 | "!$ c #EAE1DB", 481 | "~$ c #E9E2DD", 482 | "{$ c #E8E1DE", 483 | "]$ c #CCC8C5", 484 | "^$ c #A5A3A1", 485 | "/$ c #51504F", 486 | "($ c #ADADAD", 487 | "_$ c #A58A7A", 488 | ":$ c #3D2518", 489 | "<$ c #200F02", 490 | "[$ c #2E231C", 491 | "}$ c #453B35", 492 | "|$ c #605650", 493 | "1$ c #736A64", 494 | "2$ c #716A65", 495 | "3$ c #5E5954", 496 | "4$ c #403C39", 497 | "5$ c #252321", 498 | "6$ c #090604", 499 | "7$ c #444444", 500 | "8$ c #EECFBB", 501 | "9$ c #C2A796", 502 | "0$ c #574236", 503 | "a$ c #2B1302", 504 | "b$ c #B3B3B3", 505 | "c$ c #909090", 506 | "d$ c #DEC4B3", 507 | "e$ c #998477", 508 | "f$ c #412F26", 509 | "g$ c #251102", 510 | "h$ c #2B2B2B", 511 | "i$ c #D7D7D7", 512 | "j$ c #212121", 513 | "k$ c #EDD4C4", 514 | "l$ c #D9C2B3", 515 | "m$ c #A39186", 516 | "n$ c #584940", 517 | "o$ c #30221B", 518 | "p$ c #1F1004", 519 | "q$ c #190A00", 520 | "r$ c #0B0400", 521 | "s$ c #0C0804", 522 | "t$ c #21201E", 523 | "u$ c #464646", 524 | "v$ c #D0D0D0", 525 | "w$ c #454545", 526 | "x$ c #EED9CA", 527 | "y$ c #E9D6C9", 528 | "z$ c #CDBBAF", 529 | "A$ c #B4A69D", 530 | "B$ c #9A8F87", 531 | "C$ c #786E67", 532 | "D$ c #6A615B", 533 | "E$ c #655E59", 534 | "F$ c #76706C", 535 | "G$ c #95908C", 536 | "H$ c #B0ADAB", 537 | "I$ c #C7C5C3", 538 | "J$ c #E6E5E5", 539 | "K$ c #DDDDDD", 540 | "L$ c #656565", 541 | "M$ c #EDDED4", 542 | "N$ c #EADED7", 543 | "O$ c #EAE1DA", 544 | "P$ c #EAE3DD", 545 | "Q$ c #ECE5E1", 546 | "R$ c #040404", 547 | "S$ c #737373", 548 | "T$ c #747474", 549 | "U$ c #D5D5D5", 550 | "V$ c #AAAAAA", 551 | "W$ c #5E5E5E", 552 | "X$ c #232323", 553 | "Y$ c #020304", 554 | "Z$ c #D3D3D3", 555 | "`$ c #CACACA", 556 | " % c #999A9A", 557 | ".% c #464749", 558 | "+% c #191C1E", 559 | "@% c #01060B", 560 | "#% c #404040", 561 | "$% c #E9EAEB", 562 | "%% c #E1E3E6", 563 | "&% c #BBBEC2", 564 | "*% c #858A8D", 565 | "=% c #363A3F", 566 | "-% c #0C131A", 567 | ";% c #000A13", 568 | ">% c #EAEBEC", 569 | ",% c #E7EAEC", 570 | "'% c #E5E9ED", 571 | ")% c #E1E6EB", 572 | "!% c #D3D9E0", 573 | "~% c #A8AFB6", 574 | "{% c #686F76", 575 | "]% c #282E35", 576 | "^% c #05111D", 577 | "/% c #AEAEAE", 578 | "(% c #E3E8ED", 579 | "_% c #E0E6ED", 580 | ":% c #DCE4ED", 581 | "<% c #D7E1EA", 582 | "[% c #C3CDD8", 583 | "}% c #97A1AC", 584 | "|% c #505964", 585 | "1% c #1C2631", 586 | "2% c #011223", 587 | "3% c #011C39", 588 | "4% c #1B304A", 589 | "5% c #4D6884", 590 | "6% c #3CB9E3", 591 | "7% c #A3A3A3", 592 | "8% c #494949", 593 | "9% c #DDE5ED", 594 | "0% c #DAE4ED", 595 | "a% c #D8E3EE", 596 | "b% c #D5E1EE", 597 | "c% c #CFDCEA", 598 | "d% c #B1BFCE", 599 | "e% c #8592A0", 600 | "f% c #3C4856", 601 | "g% c #122131", 602 | "h% c #00152B", 603 | "i% c #011933", 604 | "j% c #1F3148", 605 | "k% c #6B8199", 606 | "l% c #9DBAD6", 607 | "m% c #AECEEE", 608 | "n% c #5ACFFA", 609 | "o% c #E9E6E4", 610 | "p% c #E7E6E6", 611 | "q% c #727272", 612 | "r% c #2D2D2D", 613 | "s% c #D2E0EE", 614 | "t% c #D0DEEE", 615 | "u% c #CCDCED", 616 | "v% c #C4D6E8", 617 | "w% c #A0B2C4", 618 | "x% c #708092", 619 | "y% c #2C3B4C", 620 | "z% c #112439", 621 | "A% c #5A6C81", 622 | "B% c #A1BAD4", 623 | "C% c #B6D1EE", 624 | "D% c #B5D2F0", 625 | "E% c #B1D1F1", 626 | "F% c #EADDD4", 627 | "G% c #BEB3AC", 628 | "H% c #B6AEA9", 629 | "I% c #B3ADA8", 630 | "J% c #AFAAA7", 631 | "K% c #9E9B98", 632 | "L% c #6C6A69", 633 | "M% c #414040", 634 | "N% c #262626", 635 | "O% c #D0DFEE", 636 | "P% c #CDDEEE", 637 | "Q% c #CBDDEF", 638 | "R% c #C8DBEF", 639 | "S% c #C3D7ED", 640 | "T% c #B7CCE3", 641 | "U% c #9AB0C7", 642 | "V% c #B8D1EB", 643 | "W% c #BAD5F0", 644 | "X% c #B8D3F0", 645 | "Y% c #E1D3C9", 646 | "Z% c #897F78", 647 | "`% c #221913", 648 | " & c #181009", 649 | ".& c #130C05", 650 | "+& c #0C0501", 651 | "@& c #9E9E9E", 652 | "#& c #C5D9EF", 653 | "$& c #C2D8EF", 654 | "%& c #C0D8F0", 655 | "&& c #BDD6F0", 656 | "*& c #59CEFA", 657 | "=& c #D4C4BA", 658 | "-& c #685E57", 659 | ";& c #190D04", 660 | ">& c #969696", 661 | ",& c #B0D0F0", 662 | "'& c #4DC5F0", 663 | ")& c #EDD9CC", 664 | "!& c #C1B0A5", 665 | "~& c #473B34", 666 | "{& c #190B01", 667 | "]& c #8D8D8D", 668 | "^& c #EAD5C7", 669 | "/& c #A59488", 670 | "(& c #34261F", 671 | "_& c #E2CABB", 672 | ":& c #88786D", 673 | "<& c #29180C", 674 | "[& c #EED4C2", 675 | "}& c #D3BCAC", 676 | "|& c #68564C", 677 | "1& c #251103", 678 | "2& c #EED1BE", 679 | "3& c #BFA797", 680 | "4& c #4B382D", 681 | "5& c #6C6C6C", 682 | "6& c #EBCCB9", 683 | "7& c #A48B7B", 684 | "8& c #3B2519", 685 | "9& c #E0C1AC", 686 | "0& c #886F60", 687 | "a& c #EFCBB2", 688 | "b& c #D3B39E", 689 | "c& c #694F40", 690 | "d& c #331602", 691 | "e& c #F88E5C", 692 | "f& c #BE9C85", 693 | "g& c #513526", 694 | "h& c #D56022", 695 | "i& c #492611", 696 | "j& c #3E3E3E", 697 | "k& c #191919", 698 | "l& c #1E1E1E", 699 | "m& c #545454", 700 | "n& c #A4A4A4", 701 | "o& c #D2D2D2", 702 | "p& c #E7E8E9", 703 | "q& c #E7E9EC", 704 | "r& c #696A6B", 705 | "s& c #ACAFB1", 706 | "t& c #D5D9DC", 707 | "u& c #E0E6EB", 708 | "v& c #DFE6ED", 709 | "w& c #0A0C0F", 710 | "x& c #323437", 711 | "y& c #7C8185", 712 | "z& c #B1B7BD", 713 | "A& c #D5DDE5", 714 | "B& c #D9E2EC", 715 | "C& c #D8E2EE", 716 | "D& c #00060B", 717 | "E& c #13181D", 718 | "F& c #3F444A", 719 | "G& c #8B929A", 720 | "H& c #B5BFCA", 721 | "I& c #D1DDEA", 722 | "J& c #010B14", 723 | "K& c #1C232A", 724 | "L& c #555D67", 725 | "M& c #C9D6E4", 726 | "N& c #111B25", 727 | "O& c #A6B3C0", 728 | "P& c #CFDEEE", 729 | "Q& c #C4D8EE", 730 | "R& c #7A8590", 731 | "S& c #CEDDEC", 732 | "T& c #A7BACE", 733 | "U& c #9AAEC4", 734 | "V& c #BAD1E9", 735 | "W& c #BCD4EF", 736 | "X& c #2E3741", 737 | "Y& c #C1CFDF", 738 | "Z& c #B6CADF", 739 | "`& c #39485A", 740 | " * c #36465A", 741 | ".* c #788CA2", 742 | "+* c #9DB6D0", 743 | "@* c #B4CFEC", 744 | "#* c #05121F", 745 | "$* c #8C98A6", 746 | "%* c #CCDDEE", 747 | "&* c #C4D9EE", 748 | "** c #94A8BC", 749 | "=* c #14253A", 750 | "-* c #011934", 751 | ";* c #172A41", 752 | ">* c #42576F", 753 | ",* c #7E97B1", 754 | "'* c #9EBDDD", 755 | ")* c #58CEF9", 756 | "!* c #333D49", 757 | "~* c #BBCCDC", 758 | "{* c #BFD5EC", 759 | "]* c #73869A", 760 | "^* c #061D37", 761 | "/* c #03203D", 762 | "(* c #1C3652", 763 | "_* c #18A8D3", 764 | ":* c #021120", 765 | "<* c #768390", 766 | "[* c #C8DAEC", 767 | "}* c #BBD2EA", 768 | "|* c #697B91", 769 | "1* c #061F39", 770 | "2* c #172230", 771 | "3* c #9CACBD", 772 | "4* c #C7DBEE", 773 | "5* c #B8D0EA", 774 | "6* c #70859D", 775 | "7* c #132842", 776 | "8* c #2E3A48", 777 | "9* c #ACBFD1", 778 | "0* c #C4D9EF", 779 | "a* c #B8D2ED", 780 | "b* c #8CA5BF", 781 | "c* c #31465F", 782 | "d* c #032544", 783 | "e* c #001225", 784 | "f* c #3D4B5A", 785 | "g* c #ADC1D6", 786 | "h* c #B7D3F0", 787 | "i* c #A8C5E2", 788 | "j* c #738EAA", 789 | "k* c #1BA8D3", 790 | "l* c #011427", 791 | "m* c #3B4A5B", 792 | "n* c #A7BBD1", 793 | "o* c #C0D7EF", 794 | "p* c #59CEF9", 795 | "q* c #2A394C", 796 | "r* c #93A8BE", 797 | "s* c #BAD3ED", 798 | "t* c #6A7D94", 799 | "u* c #A9C3DD", 800 | "v* c #B7D2EF", 801 | "w* c #021A34", 802 | "x* c #2B3D54", 803 | "y* c #7A91AA", 804 | "z* c #A6C3E0", 805 | "A* c #AFCFEF", 806 | "B* c #031E3A", 807 | "C* c #253A53", 808 | "D* c #617C98", 809 | "E* c #41BDE8", 810 | "F* c #01A1CC", 811 | "G* c #029FC5", 812 | "H* c #061014", 813 | "I* c #010B0F", 814 | "J* c #000306", 815 | "K* c #00060C", 816 | "L* c #000811", 817 | "M* c #000A15", 818 | "N* c #000B18", 819 | "O* c #000C1A", 820 | "P* c #001123", 821 | "Q* c #001328", 822 | "R* c #00142A", 823 | "S* c #00172E", 824 | "T* c #001B34", 825 | "U* c #0081A5", 826 | "V* c #00A6CF", 827 | "W* c #00A6D0", 828 | "X* c #00A5CD", 829 | "Y* c #007D9B", 830 | "Z* c #00060A", 831 | "`* c #0F0300", 832 | " = c #A44000", 833 | ".= c #D05300", 834 | "+= c #CF5200", 835 | "@= c #A34000", 836 | "#= c #311300", 837 | "$= c #2C1100", 838 | "%= c #250E00", 839 | "&= c #200C00", 840 | "*= c #1C0B00", 841 | "== c #1A0A00", 842 | "-= c #180900", 843 | ";= c #150800", 844 | ">= c #0E0600", 845 | ",= c #0C0500", 846 | "'= c #030100", 847 | ")= c #000001", 848 | "!= c #000C14", 849 | "~= c #00131C", 850 | "{= c #00121A", 851 | "]= c #140400", 852 | "^= c #1C0600", 853 | "/= c #1B0600", 854 | "(= c #130300", 855 | "_= c #020000", 856 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 857 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 858 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 859 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 860 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 861 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 862 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 863 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 864 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 865 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 866 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 867 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 868 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 869 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 870 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 871 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 872 | " . . . . . . . . . . . . . . . . . . + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < < < [ } | . . . . . . . . . . . . . . . . . . . . . . . 1 2 3 3 3 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 873 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v w x y z A B C D E F G H I J K K K L M N . . . . . . . . . . . . . . . . . . . . . . . O P Q Q Q Q P R S T U V W X Y Z ` ...+.@.#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 874 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` .(._.:.<.[.}.|.1.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 875 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.. . . . . . . . . . . . . . . . . . . . . . . . . . . ", 876 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.. . . . . . . . . . . . . . . . . . . . . . . . ", 877 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.D.E.F.G.H.I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.Q.R.S.T.U.. . . . . . . . . . . . . . . . . . . . . . ", 878 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P V.W.X.Y.Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P..+++@+#+. . . . . . . . . . . . . . . . . . . . ", 879 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q $+%+&+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.P.R.-+;+. . . . . . . . . . . . . . . . . . . ", 880 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q >+,+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.P.P.Q.)+!+~+. . . . . . . . . . . . . . . . . ", 881 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.P.P.P.P.^+/+(+. . . . . . . . . . . . . . . . ", 882 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.P.P.P.P.P._+:+#+. . . . . . . . . . . . . . . ", 883 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.<+[+}+|+1+2+3+v.N.O.P.P.P.P.P.P.P.P.P.P.P.P.4+5+6+. . . . . . . . . . . . . . ", 884 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.7+8+9+0+a+b+c+d+e+f+g+h+i+Q.P.P.P.P.P.P.P.P.P.P.P.P.j+k+~+. . . . . . . . . . . . . ", 885 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.l+m+n+o+p+q+r++.s+#.$.%.i t+u+v+w+x+y+P.P.P.P.P.P.P.P.P.P.P.z+A+. . . . . . . . . . . . . ", 886 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+B+C+D+E+F+` ...+.s+#.$.%.i &.*.n G+H+/+I+J+P.P.P.P.P.P.P.P.P.P.K+L+. . . . . . . . . . . . ", 887 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+M+N+O+P+Y /.` ...+.s+#.$.%.i &.*.n . . G+Q+R+.+P.P.P.P.P.P.P.P.P.Q.S+(+. . . . . . . . . . . ", 888 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+T+U+V+W+].^.Y /.X+Y+Z+`+ @.@+@@@#@$@%@n . . . . &@*@=@P.P.P.P.P.P.P.P.P.=@-@. . . . . . . . . . . ", 889 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+;@>@,@{.].^.'@)@!@~@{@]@^@/@(@_@:@<@[@}@|@. . . . 1@2@R.P.P.P.P.P.P.P.P.P.3@4@. . . . . . . . . . ", 890 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+5@6@7@U {.].8@9@0@a@b@o.p.q.r.s.t.u.M.c@d@e@f@1@. . . g@h@.+P.P.P.P.P.P.P.P.i@T.. . . . . . . . . . ", 891 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q j@k@l@T U {.m@n@o@J.K.L.o.p.q.r.s.t.u.M.N.O.P.p@q@r@. . . r@R+J+P.P.P.P.P.P.P.P.s@t@. . . . . . . . . ", 892 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q u@v@~.T U h.w@x@I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.y+y@r@. . . z@A@P.P.P.P.P.P.P.P.B@C@. . . . . . . . . ", 893 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q D@E@~.T F@G@H@ +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.y+:+1@. . G+k+I@P.P.P.P.P.P.P.Q.A.. . . . . . . . . ", 894 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.J@K@L@`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.p@M@. . . N@O@P.P.P.P.P.P.P.P.P@C.. . . . . . . . ", 895 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.Q@R@Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.S@T@. . G+U@Q.P.P.P.P.P.P.P.V@z@. . . . . . . . ", 896 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.W@X@Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.y+Y@. . . Z@p@P.P.P.P.P.P.P.y+A+. . . . . . . . ", 897 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R `@ #.#Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.s@+#. . g.@#P.P.P.P.P.P.P.Q.5+. . . . . . . . ", 898 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ##$#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.%#;+. . G+&#P.P.P.P.P.P.P.P.*#G+. . . . . . . ", 899 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R =#-#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.y+;#. . . 2@I@P.P.P.P.P.P.P.>#g@. . . . . . . ", 900 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ,#'#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.I@)#. . . !#y+P.P.P.P.P.P.P.P@&@. . . . . . . ", 901 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~#{#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.Q.]#. . . ^#y+P.P.P.P.P.P.P.@#g.. . . . . . . ", 902 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R /#{#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.Q.*@. . . (#y+P.P.P.P.P.P.P._#:#. . . . . . . ", 903 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R <#'#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.I@[#. . . T.y+P.P.P.P.P.P.P.P@C.. . . . . . . ", 904 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R }#|#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.y+1#. . . 2#Q.P.P.P.P.P.P.P.>#g@. . . . . . . ", 905 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R 3#4#=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.5#6#. . 7#8#P.P.P.P.P.P.P.P.9#. . . . . . . . ", 906 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R 0#a#b#Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.c#6+. . d#e#P.P.P.P.P.P.P.Q.*@. . . . . . . . ", 907 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.f#g#Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.i@h#. . . i#j+P.P.P.P.P.P.P.y+j#. . . . . . . . ", 908 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.k#l#m#`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.n#o#. . G+p#Q.P.P.P.P.P.P.P.%#;+. . . . . . . . ", 909 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T q#r#l+ +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.z+s#. . . t#I+P.P.P.P.P.P.P.P.3@u#. . . . . . . . ", 910 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q v#w#~.T x#y#z# +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.4+A#~+. . 7#]#I@P.P.P.P.P.P.P.Q.B#. . . . . . . . . ", 911 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q C#D#~.T U E#F#G#H#J.K.L.o.p.q.r.s.t.u.M.N.O.P.P._+I#J#. . . C@5#P.P.P.P.P.P.P.P.V@K#. . . . . . . . . ", 912 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q L#M#N#T U {.O#P#Q#R#K.L.o.p.q.r.s.t.u.M.N.O.J+%#S#(+. . . T@>#J+P.P.P.P.P.P.P.J+8#(+. . . . . . . . . ", 913 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+T#U#V#U {.].W#X#Y#Z#`#o.p.q.r.s.t.u.M. $.$+$@$7#. . . +##$I@P.P.P.P.P.P.P.P._+$$. . . . . . . . . . ", 914 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+%$&$*${.].^.'@=$-$;$>$,$'$)$!$~${$]$^$/$&@. . . . t@:+i@P.P.P.P.P.P.P.P.J+($C.. . . . . . . . . . ", 915 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+T+-#_$:$].^.Y /.` <$[$}$|$1$2$3$4$5$6$n . . . . |@#$i@P.P.P.P.P.P.P.P.P.V@7$. . . . . . . . . . . ", 916 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+8$9$0$a$Y /.` ...+.s+#.$.%.i &.*.n . . 7#B.b$I@P.P.P.P.P.P.P.P.P.I@c$1@. . . . . . . . . . . ", 917 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.d$e$f$g$` ...+.s+#.$.%.i &.*.n 7#h$A.i$J+P.P.P.P.P.P.P.P.P.P.S@j$. . . . . . . . . . . . ", 918 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`.k$l$m$n$o$p$q$s+#.$.%.r$s$t$u$S+v$Q.P.P.P.P.P.P.P.P.P.P.P.5#w$. . . . . . . . . . . . . ", 919 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.x$y$z$A$B$C$D$E$F$G$H$I$J$J+P.P.P.P.P.P.P.P.P.P.P.P.K$L$G+. . . . . . . . . . . . . ", 920 | ". . . . . . . . . . . . . 7#. . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.M$^@N$O$P$Q$v.N.O.P.P.P.P.P.P.P.P.P.P.P.P.p@2@R$. . . . . . . . . . . . . . ", 921 | ". . . . . . . . . . . . (+5+S$;+g@. . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.P.P.P.P.P.K$T$1@. . . . . . . . . . . . . . . ", 922 | ". . . . . . . . . . . . t@n#I@U$V$W$X$Y$p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.P.P.P.P.Z$L$R$. . . . . . . . . . . . . . . . ", 923 | ". . . . . . . . . . . . (+S.P.P.P.y+`$ %.%+%@%r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.P.P.I@S@#%G+. . . . . . . . . . . . . . . . . ", 924 | ". . . . . . . . . . . . 1@>#P.P.P.P.P.$%%%&%*%=%-%;%u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.P.P.J+^+A.N@. . . . . . . . . . . . . . . . . . . ", 925 | ". . . . . . . . . . . . ~++$P.P.P.P.P.>%,%'%)%!%~%{%]%^%=.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.P.P.J+p@&#@$R$. . . . . . . . . . . . . . . . . . . . ", 926 | ". . . . . . . . . . . . 7#/%P.P.P.P.P.>%,%'%(%_%:%<%[%}%|%1%2%z A B C >.E ,.3%4%5%6%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.M.N.O.P.P.I@U$7%8%#+. . . . . . . . . . . . . . . . . . . . . . ", 927 | ". . . . . . . . . . . . G+/%P.P.P.P.P.>%,%'%(%_%9%0%a%b%c%d%e%f%g%h%C >.i%j%k%l%m%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.q.r.s.t.u.v.o%p%v$/%q%r%R$. . . . . . . . . . . . . . . . . . . . . . . . ", 928 | ". . . . . . . . . . . . . ($P.P.P.P.P.>%,%'%(%_%9%0%a%b%s%t%u%v%w%x%y%z%A%B%C%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.p.F%G%H%I%J%K%L%M%N%g@. . . . . . . . . . . . . . . . . . . . . . . . . . . ", 929 | ". . . . . . . . . . . . . 9#P.P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%S%T%U%V%W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.L.o.Y%Z%`% &.&+&&.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 930 | ". . . . . . . . . . . . . @&J+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%*&K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.K.`#=&-&;&#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 931 | ". . . . . . . . . . . . . >&J+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%,&'&K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.J.)&!&~&{&s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 932 | ". . . . . . . . . . . . . ]&Q.P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +I.^&/&(&..+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 933 | ". . . . . . . . . . . . . ]#Q.P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.`. +_&:&<& ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 934 | ". . . . . . . . . . . . . B#Q.P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+Z.[&}&|&1&` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 935 | ". . . . . . . . . . . . . T$I@P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+=+2&3&4&'@/.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 936 | ". . . . . . . . . . . . . 5&I@P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+'+*+6&7&8&^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 937 | ". . . . . . . . . . . . . Y@I@P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+]+T+9&0&h.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 938 | ". . . . . . . . . . . . . T.y+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q {+a&b&c&d&{.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 939 | ". . . . . . . . . . . . . -@y+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q e&f&g&J@U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 940 | ". . . . . . . . . . . . . (#y+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q h&i&~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 941 | ". . . . . . . . . . . . . s#y+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 942 | ". . . . . . . . . . . . . @$y+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 943 | ". . . . . . . . . . . . . j&y+P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 944 | ". . . . . . . . . . . . . C@i@P.P.P.P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 945 | ". . . . . . . . . . . . . k&y@x+.+J+P.>%,%'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 946 | ". . . . . . . . . . . . . . G+l&m&n&o&p&q&'%(%_%9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 947 | ". . . . . . . . . . . . . . . . . R$6#r&s&t&u&v&9%0%a%b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 948 | ". . . . . . . . . . . . . . . . . . . @ w&x&y&z&A&B&C&b%s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 949 | ". . . . . . . . . . . . . . . . . . . @ p & D&E&F&G&H&I&s%O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 950 | ". . . . . . . . . . . . . . . . . . . @ p & q r s J&K&L&M&O%P%Q%R%#&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 951 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u N&O&P&P%Q%R%Q&$&%&&&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 952 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v R&S&P%Q%R%T&U&V&W&W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 953 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v X&Y&P%Q%R%Z&`& *.*+*@*D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 954 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v #*$*%*Q%R%&***=*-*;*>*,*'*)*K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 955 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.!*~*Q%R%#&{*]*^*,.'./*(*_*K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 956 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.:*<*[*R%#&$&}*|*1*'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 957 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.2*3*4*#&$&%&5*6*7*H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 958 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.8*9*0*$&%&&&a*b*c*d*).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 959 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.e*f*g*$&%&&&W%h*i*j*k*K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 960 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z l*m*n*o*&&W%X%D%,&p*K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 961 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A h%q*r*s*W%X%D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 962 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C =*t*u*v*D%E%n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 963 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.w*x*y*z*A*n%K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 964 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.B*C*D*E*K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 965 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I F*K K K K G*H*R$G+. . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 966 | ". . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M I*. . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 967 | " . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 968 | " . . . . . . . . . . . . . . . . . . @ p & q r s t u v =.-.;.z A B C >.E ,.'.H I ).K K K K M N . . . . . . . . . . . . . . . . . . . . . . . O !.Q Q Q Q P R ~.T U {.].^.Y /.` ...+.s+#.$.%.i &.*.n . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 969 | " . . . . . . . . . . . . . . . . . . + # J*& * K*r L*t M*N*O*=.x y P*e*Q*R*_ S*T*U*V*V*W*X*Y*Z*. . . . . . . . . . . . . . . . . . . . . . . `* =.=+=+=+=@=#=$=X Y %=Z &= .*===-=;=#.$.>=,=i j l '=o . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 970 | " . . . . . . . . . . . . . . . . . . . . . . . . . . )=)=)=)=)=)=)=)=+ + + @ @ @ !=~=~=~={=N . . . . . . . . . . . . . . . . . . . . . . . . . ]=^=^=^=/=(=n _=o o o o o o o o o o o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 971 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 972 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 973 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 974 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 975 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 976 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 977 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 978 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 979 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 980 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 981 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 982 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", 983 | " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; 984 | -------------------------------------------------------------------------------- /RemotePlayWhatever/appresource.rc: -------------------------------------------------------------------------------- 1 | ID_APPICON ICON "appicon.ico" -------------------------------------------------------------------------------- /RemotePlayWhatever/wxSteamStuff.cpp: -------------------------------------------------------------------------------- 1 | #include "wxSteamStuff.h" 2 | 3 | wxBitmap SteamImageToBitmap(int imageID) 4 | { 5 | uint32 imgHeight, imgWidth; 6 | wxImage wImage; 7 | if(GClientContext()->SteamUtils()->GetImageSize(imageID, &imgWidth, &imgHeight)) 8 | { 9 | size_t bufSize = imgHeight * imgWidth; 10 | uint32_t* buf = new uint32_t[bufSize]; 11 | 12 | if(GClientContext()->SteamUtils()->GetImageRGBA(imageID, (uint8_t*)buf, bufSize * 4)) 13 | { 14 | size_t imgSize = bufSize * 3; 15 | uint8_t* imBuf = (uint8_t*)malloc(imgSize); 16 | for(size_t i = 0; i < bufSize; ++i) 17 | { 18 | int offset = i * 3; 19 | imBuf[offset] = ((uint8_t*)&buf[i])[0]; 20 | imBuf[offset + 1] = ((uint8_t*)&buf[i])[1]; 21 | imBuf[offset + 2] = ((uint8_t*)&buf[i])[2]; 22 | } 23 | wImage.SetData(imBuf, imgWidth, imgHeight); 24 | } 25 | 26 | delete[] buf; 27 | } 28 | 29 | return wxBitmap(wImage); 30 | } 31 | 32 | wxSteamID::wxSteamID(CSteamID steamID): 33 | m_steamID(steamID) 34 | { 35 | } 36 | 37 | CSteamID wxSteamID::GetSteamID() 38 | { 39 | return m_steamID; 40 | } 41 | -------------------------------------------------------------------------------- /RemotePlayWhatever/wxSteamStuff.h: -------------------------------------------------------------------------------- 1 | #ifndef WXSTEAMSTUFF_H 2 | #define WXSTEAMSTUFF_H 3 | #include 4 | #include "SteamStuff.h" 5 | 6 | class wxSteamID : public wxObject 7 | { 8 | public: 9 | wxSteamID(CSteamID steamID); 10 | CSteamID GetSteamID(); 11 | 12 | private: 13 | CSteamID m_steamID; 14 | }; 15 | 16 | wxBitmap SteamImageToBitmap(int imageID); 17 | 18 | #endif // WXSTEAMSTUFF_H 19 | -------------------------------------------------------------------------------- /assets/rpw_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m4dEngi/RemotePlayWhatever/bb549888e1d5d22db133b2e18dfc831dd6968027/assets/rpw_screen.png --------------------------------------------------------------------------------