diff --git a/Playstation/OrbisLibAPI/Apps.cpp b/Playstation/OrbisLibAPI/Apps.cpp index 80f7ccc..80b3e09 100644 --- a/Playstation/OrbisLibAPI/Apps.cpp +++ b/Playstation/OrbisLibAPI/Apps.cpp @@ -48,6 +48,18 @@ void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet) KillApp(Sock, titleId); + break; + + case API_APPS_SUSPEND: + + SuspendApp(Sock, titleId); + + break; + + case API_APPS_RESUME: + + ResumeApp(Sock, titleId); + break; } } @@ -77,21 +89,17 @@ void Apps::GetAppInfoString(OrbisNetId Sock, const char* TitleId) char KeyValue[50]; sceNetRecv(Sock, KeyValue, sizeof(KeyValue), 0); - klog("TitleId: %s\n", TitleId); - klog("Key: %s\n", KeyValue); - // Look up the key for that titleId in the app.db. char OutStr[200]; memset(OutStr, 0, sizeof(OutStr)); AppDatabase::GetAppInfoString(TitleId, OutStr, sizeof(OutStr), KeyValue); - klog("OutStr: %s\n", OutStr); - // Send back the result. sceNetSend(Sock, OutStr, sizeof(OutStr), 0); } -void Apps::SendAppStatus(OrbisNetId Sock, const char* TitleId) +// TODO: Currently cant get the appId of child processes like the Web Browser since it is a child of the ShellUI. +int Apps::GetAppId(const char* TitleId) { int appId = 0; @@ -114,6 +122,13 @@ void Apps::SendAppStatus(OrbisNetId Sock, const char* TitleId) } } + return appId; +} + +void Apps::SendAppStatus(OrbisNetId Sock, const char* TitleId) +{ + auto appId = GetAppId(TitleId); + // If we have no appId that means the process is not running. if (appId <= 0) { @@ -161,26 +176,7 @@ void Apps::StartApp(OrbisNetId Sock, const char* TitleId) void Apps::KillApp(OrbisNetId Sock, const char* TitleId) { - int appId = 0; - - // Get the list of running processes. - std::vector processList; - GetProcessList(processList); - - for (const auto& i : processList) - { - // Get the app info using the pid. - OrbisAppInfo appInfo; - sceKernelGetAppInfo(i.pid, &appInfo); - - // Using the titleId match our desired app and return the appId from the appinfo. - if (!strcmp(appInfo.TitleId, TitleId)) - { - appId = appInfo.AppId; - - break; - } - } + auto appId = GetAppId(TitleId); if (appId > 0 && sceSystemServiceKillApp(appId, -1, 0, 0) == 0) { @@ -192,6 +188,34 @@ void Apps::KillApp(OrbisNetId Sock, const char* TitleId) } } +void Apps::SuspendApp(OrbisNetId Sock, const char* TitleId) +{ + auto appId = GetAppId(TitleId); + + if (appId > 0 && LncUtil::sceLncUtilSuspendApp(appId, 0) == 0) + { + SockSendInt(Sock, 1); + } + else + { + SockSendInt(Sock, 0); + } +} + +void Apps::ResumeApp(OrbisNetId Sock, const char* TitleId) +{ + auto appId = GetAppId(TitleId); + + if (appId > 0 && LncUtil::sceLncUtilResumeApp(appId, 0) == 0) + { + SockSendInt(Sock, 1); + } + else + { + SockSendInt(Sock, 0); + } +} + Apps::Apps() { diff --git a/Playstation/OrbisLibAPI/Apps.h b/Playstation/OrbisLibAPI/Apps.h index a5e0b5d..7366bc0 100644 --- a/Playstation/OrbisLibAPI/Apps.h +++ b/Playstation/OrbisLibAPI/Apps.h @@ -13,7 +13,10 @@ public: private: void GetAppsList(OrbisNetId Sock); void GetAppInfoString(OrbisNetId Sock, const char* TitleId); + int GetAppId(const char* TitleId); void SendAppStatus(OrbisNetId Sock, const char* TitleId); void StartApp(OrbisNetId Sock, const char* TitleId); void KillApp(OrbisNetId Sock, const char* TitleId); + void SuspendApp(OrbisNetId Sock, const char* TitleId); + void ResumeApp(OrbisNetId Sock, const char* TitleId); }; diff --git a/Playstation/OrbisLibAPI/LncUtil.cpp b/Playstation/OrbisLibAPI/LncUtil.cpp index 2e3913d..503addc 100644 --- a/Playstation/OrbisLibAPI/LncUtil.cpp +++ b/Playstation/OrbisLibAPI/LncUtil.cpp @@ -4,6 +4,8 @@ uint64_t LncUtil::LibraryBaseAddress = 0; int(*LncUtil::_sceLncUtilGetAppId)(const char*); int(*LncUtil::_sceLncUtilLaunchApp)(const char* titleId, char* args, LaunchAppParam* appParam); +int(*LncUtil::_sceLncUtilSuspendApp)(int AppId, int Flag); +int(*LncUtil::_sceLncUtilResumeApp)(int AppId, int Flag); int LncUtil::Init() { @@ -45,6 +47,8 @@ int LncUtil::Init() // Set up Functions. _sceLncUtilGetAppId = (decltype(_sceLncUtilGetAppId))(LibraryBaseAddress + 0x4E10); _sceLncUtilLaunchApp = (decltype(_sceLncUtilLaunchApp))(LibraryBaseAddress + 0x4C10); + _sceLncUtilSuspendApp = (decltype(_sceLncUtilSuspendApp))(LibraryBaseAddress + 0x4F20); + _sceLncUtilResumeApp = (decltype(_sceLncUtilResumeApp))(LibraryBaseAddress + 0x4F40); return 0; } @@ -70,17 +74,33 @@ int LncUtil::sceLncUtilLaunchApp(const char* titleId, char* args, LaunchAppParam } else { - klog("failed to resolve sceLncUtilGetAppId\n"); + klog("failed to resolve sceLncUtilLaunchApp\n"); return -1; } } -/*int SuspensceLncUtilSuspendAppdApp(int AppId, int Flag) +int LncUtil::sceLncUtilSuspendApp(int AppId, int Flag) { - + if ((uint64_t)_sceLncUtilSuspendApp > 0x4F20) + { + return _sceLncUtilSuspendApp(AppId, Flag); + } + else + { + klog("failed to resolve sceLncUtilSuspendApp\n"); + return -1; + } } -int sceLncUtilResumeApp(int AppId, int Flag) +int LncUtil::sceLncUtilResumeApp(int AppId, int Flag) { - -}*/ + if ((uint64_t)_sceLncUtilResumeApp > 0x4F40) + { + return _sceLncUtilResumeApp(AppId, Flag); + } + else + { + klog("failed to resolve sceLncUtilResumeApp\n"); + return -1; + } +} diff --git a/Playstation/OrbisLibAPI/LncUtil.h b/Playstation/OrbisLibAPI/LncUtil.h index f694a06..e1c347e 100644 --- a/Playstation/OrbisLibAPI/LncUtil.h +++ b/Playstation/OrbisLibAPI/LncUtil.h @@ -46,9 +46,13 @@ public: static int Init(); static int sceLncUtilGetAppId(const char* TitleId); static int sceLncUtilLaunchApp(const char* titleId, char* args, LaunchAppParam* appParam); + static int sceLncUtilSuspendApp(int AppId, int Flag); + static int sceLncUtilResumeApp(int AppId, int Flag); private: static uint64_t LibraryBaseAddress; static int(*_sceLncUtilGetAppId)(const char* titleId); static int(*_sceLncUtilLaunchApp)(const char* titleId, char* args, LaunchAppParam* appParam); + static int(*_sceLncUtilSuspendApp)(int AppId, int Flag); + static int(*_sceLncUtilResumeApp)(int AppId, int Flag); }; diff --git a/Playstation/OrbisLibAPI/Version.h b/Playstation/OrbisLibAPI/Version.h index d897bfe..caf5cd6 100644 --- a/Playstation/OrbisLibAPI/Version.h +++ b/Playstation/OrbisLibAPI/Version.h @@ -1,11 +1,11 @@ -#pragma once -#define ORBISLIB_MAJOR 3 -#define ORBISLIB_MINOR 0 -#define ORBISLIB_BUILDVERSION 635 -#define stringify(a) stringify_(a) -#define stringify_(a) #a -#if defined(_DEBUG) -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#else -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#endif +#pragma once +#define ORBISLIB_MAJOR 3 +#define ORBISLIB_MINOR 0 +#define ORBISLIB_BUILDVERSION 636 +#define stringify(a) stringify_(a) +#define stringify_(a) #a +#if defined(_DEBUG) +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#else +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#endif diff --git a/Windows/Libraries/OrbisLib/Classes/Target/Application.cs b/Windows/Libraries/OrbisLib/Classes/Target/Application.cs index dda697c..374d6df 100644 --- a/Windows/Libraries/OrbisLib/Classes/Target/Application.cs +++ b/Windows/Libraries/OrbisLib/Classes/Target/Application.cs @@ -188,7 +188,69 @@ namespace OrbisSuite return false; } - APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_STOP }, out Socket Sock); + var apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_STOP }, out Socket Sock); + + if (apiResult != APIResults.API_OK) + return false; + + // Send the titleId of the app. + var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray(); + Sock.Send(bytes); + + // Get the state from API. + var result = Sock.RecvInt32(); + + // close socket. + Sock.Close(); + + return (result == 1); + } + + public bool Suspend(string TitleId) + { + if (!Regex.IsMatch(TitleId, @"[a-zA-Z]{4}\d{5}")) + { + Console.WriteLine($"Invaild titleId format {TitleId}"); + return false; + } + + if (!Target.Info.Details.IsAPIAvailable) + { + return false; + } + + var apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_SUSPEND }, out Socket Sock); + + if (apiResult != APIResults.API_OK) + return false; + + // Send the titleId of the app. + var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray(); + Sock.Send(bytes); + + // Get the state from API. + var result = Sock.RecvInt32(); + + // close socket. + Sock.Close(); + + return (result == 1); + } + + public bool Resume(string TitleId) + { + if (!Regex.IsMatch(TitleId, @"[a-zA-Z]{4}\d{5}")) + { + Console.WriteLine($"Invaild titleId format {TitleId}"); + return false; + } + + if (!Target.Info.Details.IsAPIAvailable) + { + return false; + } + + var apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_RESUME }, out Socket Sock); if (apiResult != APIResults.API_OK) return false; diff --git a/Windows/Libraries/OrbisLib/Common/API/API.cs b/Windows/Libraries/OrbisLib/Common/API/API.cs index 531bc60..519d615 100644 --- a/Windows/Libraries/OrbisLib/Common/API/API.cs +++ b/Windows/Libraries/OrbisLib/Common/API/API.cs @@ -14,7 +14,7 @@ namespace OrbisSuite.Common { Sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - return Sock.EasyConnect(IPAddr, Port, 4000); + return Sock.EasyConnect(IPAddr, Port, -1); } /// diff --git a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml index db9a631..b898dd3 100644 --- a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml +++ b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml @@ -149,6 +149,17 @@ Click="StartStop_Click" Grid.Column="0"/> + + + + Grid.Column="4"/> - - - - - + - - + diff --git a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs index a8c63ef..7d26ac3 100644 --- a/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs +++ b/Windows/OrbisNeighborHood/Controls/AppPanel.xaml.cs @@ -62,7 +62,9 @@ namespace OrbisNeighborHood.Controls StartStop.ToolTip = $"Start {App.TitleName}."; Visibility.ToolTip = $"Hide {App.TitleName} from Home Menu."; ChangeIcon.ToolTip = $"Change the icon of {App.TitleName}."; - // 3 more TBD here. + SuspendResume.ToolTip = $"Not available while {App.TitleName} is not running."; + // TODO: One TBD. + MoreInfo.ToolTip = $"See more info about {App.TitleName}."; Delete.ToolTip = $"Delete {App.TitleName}."; } @@ -80,13 +82,35 @@ namespace OrbisNeighborHood.Controls // App status. if (AppState == AppState.STATE_RUNNING || AppState == AppState.STATE_SUSPENDED) { - Dispatcher.Invoke(() => StartStop.ToolTip = $"Stop {App.TitleName}."); - Dispatcher.Invoke(() => StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Stop.png"); + Dispatcher.Invoke(() => + { + StartStop.ToolTip = $"Stop {App.TitleName}."; + StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Stop.png"; + + SuspendResume.IsEnabled = true; + if (AppState == AppState.STATE_SUSPENDED) + { + SuspendResume.ToolTip = $"Resume {App.TitleName}."; + SuspendResume.ImageSource = "/OrbisNeighborHood;component/Images/Start.png"; + } + else + { + SuspendResume.ToolTip = $"Suspend {App.TitleName}."; + SuspendResume.ImageSource = "/OrbisNeighborHood;component/Images/Suspend.png"; + } + }); } else { - Dispatcher.Invoke(() => StartStop.ToolTip = $"Start {App.TitleName}."); - Dispatcher.Invoke(() => StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Start.png"); + Dispatcher.Invoke(() => + { + StartStop.ToolTip = $"Start {App.TitleName}."; + StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Start.png"; + + SuspendResume.ToolTip = $"Not available while {App.TitleName} is not running."; + SuspendResume.ImageSource = "/OrbisNeighborHood;component/Images/UnAvailable.png"; + SuspendResume.IsEnabled = false; + }); } // App Visibility. @@ -121,6 +145,22 @@ namespace OrbisNeighborHood.Controls }); } + private void SuspendResume_Click(object sender, RoutedEventArgs e) + { + Task.Run(() => + { + var currentTarget = OrbisLib.Instance.SelectedTarget; + if (AppState == AppState.STATE_SUSPENDED) + { + currentTarget.Application.Resume(App.TitleId); + } + else + { + currentTarget.Application.Suspend(App.TitleId); + } + }); + } + private void Visibility_Click(object sender, RoutedEventArgs e) { @@ -131,17 +171,12 @@ namespace OrbisNeighborHood.Controls } - private void Unknown_Click(object sender, RoutedEventArgs e) + private void OpenStore_Click(object sender, RoutedEventArgs e) { } - private void Unknown2_Click(object sender, RoutedEventArgs e) - { - - } - - private void Unknown3_Click(object sender, RoutedEventArgs e) + private void MoreInfo_Click(object sender, RoutedEventArgs e) { } diff --git a/Windows/OrbisNeighborHood/Images/Info.png b/Windows/OrbisNeighborHood/Images/Info.png new file mode 100644 index 0000000..41612e7 Binary files /dev/null and b/Windows/OrbisNeighborHood/Images/Info.png differ diff --git a/Windows/OrbisNeighborHood/Images/ReplaceIcon.png b/Windows/OrbisNeighborHood/Images/ReplaceIcon.png index cf2eb43..b519f42 100644 Binary files a/Windows/OrbisNeighborHood/Images/ReplaceIcon.png and b/Windows/OrbisNeighborHood/Images/ReplaceIcon.png differ diff --git a/Windows/OrbisNeighborHood/Images/Store.png b/Windows/OrbisNeighborHood/Images/Store.png new file mode 100644 index 0000000..6a4c510 Binary files /dev/null and b/Windows/OrbisNeighborHood/Images/Store.png differ diff --git a/Windows/OrbisNeighborHood/Images/Suspend.png b/Windows/OrbisNeighborHood/Images/Suspend.png new file mode 100644 index 0000000..02fb36d Binary files /dev/null and b/Windows/OrbisNeighborHood/Images/Suspend.png differ diff --git a/Windows/OrbisNeighborHood/Images/Visibility.png b/Windows/OrbisNeighborHood/Images/Visibility.png index e8e0bb9..1a1ee52 100644 Binary files a/Windows/OrbisNeighborHood/Images/Visibility.png and b/Windows/OrbisNeighborHood/Images/Visibility.png differ diff --git a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs index 732d660..7a3fac2 100644 --- a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs +++ b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs @@ -37,6 +37,8 @@ namespace OrbisNeighborHood.MVVM.View "NPXS20112", "NPXS20133", "NPXS20132", + "CUSA02012", // Media Player + "NPXS20979", // Playstation Store // Destiny? lol "CUSA00219", @@ -191,13 +193,10 @@ namespace OrbisNeighborHood.MVVM.View var appList = currentTarget.Application.GetAppList(); - foreach (var app in appList) + Parallel.ForEach(appList, app => { - Parallel.Invoke(() => - { - AddApp(appCachePath, app); - }); - } + AddApp(appCachePath, app); + }); } private async Task CheckAppDatabase() @@ -224,24 +223,26 @@ namespace OrbisNeighborHood.MVVM.View var appList = currentTarget.Application.GetAppList(); // Check for deletions. - foreach (var app in AppList.Items.Cast().ToList()) + Parallel.ForEach(AppList.Items.Cast().ToList(), app => { if (appList.Find(x => x.TitleId == app.App.TitleId) == null) { Dispatcher.Invoke(() => AppList.Items.Remove(app)); } - } + }); // Check for new apps / updates. - foreach (var app in appList) + Parallel.ForEach(appList, app => { - Parallel.Invoke(() => + var currentAppList = AppList.Items.Cast().ToList(); + + if (currentAppList.Find(x => x.App.TitleId == app.TitleId) == null) { AddApp(appCachePath, app); - }); - } + } + }); - await Task.Delay(1000); + await Task.Delay(2000); } catch (Exception ex) { diff --git a/Windows/OrbisNeighborHood/OrbisNeighborHood.csproj b/Windows/OrbisNeighborHood/OrbisNeighborHood.csproj index d57f277..483f435 100644 --- a/Windows/OrbisNeighborHood/OrbisNeighborHood.csproj +++ b/Windows/OrbisNeighborHood/OrbisNeighborHood.csproj @@ -25,6 +25,7 @@ + @@ -38,6 +39,8 @@ + + @@ -49,6 +52,12 @@ + + + PreserveNewest + + + PreserveNewest @@ -95,6 +104,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -134,6 +146,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt index 39c15c3..1447642 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt @@ -1 +1 @@ -1956 +1976 diff --git a/Windows/OrbisNeighborHood/Resources/BuildString.txt b/Windows/OrbisNeighborHood/Resources/BuildString.txt index f3c7c94..bc7b4c8 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildString.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildString.txt @@ -1 +1 @@ -Version 3.0.1956 Debug Build Sunday December 18 2022 7:40 PM +Version 3.0.1976 Debug Build Sunday December 18 2022 10:33 PM