diff --git a/Playstation/OrbisLibAPI/API.cpp b/Playstation/OrbisLibAPI/API.cpp index eb42df6..adc7840 100644 --- a/Playstation/OrbisLibAPI/API.cpp +++ b/Playstation/OrbisLibAPI/API.cpp @@ -67,7 +67,7 @@ void API::Init() Proc = new class Proc(); Apps = new class Apps(); Debug = new class Debug(); - Target = new class Target(); + Target = new class Target(Debug); Listener = new SocketListener(ListenerCallback, NULL, 6900); Running = true; } diff --git a/Playstation/OrbisLibAPI/APIPackets.h b/Playstation/OrbisLibAPI/APIPackets.h index a9b06a4..c2aff96 100644 --- a/Playstation/OrbisLibAPI/APIPackets.h +++ b/Playstation/OrbisLibAPI/APIPackets.h @@ -146,7 +146,8 @@ struct APIPacket struct ProcPacket { - int32_t ProcessId; + int AppId; + int ProcessId; char Name[32]; char TitleId[10]; }; @@ -162,6 +163,28 @@ enum AppState STATE_SUSPENDED, }; +struct AppInfoPacket +{ + char TitleId[10]; + char ContentId[100]; + char TitleName[200]; + char MetaDataPath[100]; + char LastAccessTime[100]; + int Visible; + int SortPriority; + int DispLocation; + bool CanRemove; + char Category[10]; + int ContentSize; + char InstallDate[100]; + char UICategory[10]; +}; + +struct AppListPacket +{ + AppInfoPacket Apps[]; +}; + #pragma endregion #pragma region Debug diff --git a/Playstation/OrbisLibAPI/Apps.cpp b/Playstation/OrbisLibAPI/Apps.cpp index ac949cd..0a49964 100644 --- a/Playstation/OrbisLibAPI/Apps.cpp +++ b/Playstation/OrbisLibAPI/Apps.cpp @@ -93,14 +93,9 @@ void Apps::GetAppsList(OrbisNetId Sock) return; } - // Send the number of apps. SockSendInt(Sock, AppList.size()); - // Send all of the apps. - for (const auto& App : AppList) - { - sceNetSend(Sock, &App, sizeof(AppDatabase::AppInfo), 0); - } + SendLargeData(Sock, (unsigned char*)AppList.data(), AppList.size() * sizeof(AppInfoPacket)); } void Apps::GetAppInfoString(OrbisNetId Sock, const char* TitleId) diff --git a/Playstation/OrbisLibAPI/Debug.cpp b/Playstation/OrbisLibAPI/Debug.cpp index d406e85..08a6df2 100644 --- a/Playstation/OrbisLibAPI/Debug.cpp +++ b/Playstation/OrbisLibAPI/Debug.cpp @@ -1,5 +1,8 @@ #include "Common.h" #include "Debug.h" +#include "APIHelper.h" + +#include void Debug::HandleAPI(OrbisNetId Sock, APIPacket* Packet) { @@ -8,10 +11,83 @@ void Debug::HandleAPI(OrbisNetId Sock, APIPacket* Packet) default: break; + case API_DBG_ATTACH: + break; + + case API_DBG_DETACH: + + break; } } +bool Debug::TryDetach(int pid) +{ + // Check if we are even attached. + if (!IsDebugging) + { + return true; + } + + // Detach from the process. + int res = ptrace(PT_DETACH, pid, nullptr, 0); + if (res != 0) + { + klog("DetachProcess(): ptrace(PT_DETACH) failed with error %llX\n", res); + return false; + } + + // TODO: Kill the watching thread and Remove any Watchpoints / Breakpoints now. + + IsDebugging = false; + CurrentPID = 0; + + return true; +} + +void Debug::Attach(OrbisNetId Sock) +{ + auto pid = RecieveInt(Sock); + + // If we are currently debugging another process lets detach from it. + if (!TryDetach(pid)) + { + klog("Attach(): TryDetach Failed. :(\n"); + SendStatus(Sock, 0); + return; + } + + // Use ptrace to attach to begin debugging this pid. + int res = ptrace(PT_ATTACH, pid, nullptr, 0); + if (res != 0) + { + klog("Attach(): ptrace(PT_ATTACH) failed with error %llX\n", res); + SendStatus(Sock, 0); + return; + } + + // Attaching by default will stop execution of the remote process. Lets continue it now. + res = ptrace(PT_CONTINUE, pid, nullptr, 0); + if (res != 0) + { + klog("Attach(): ptrace(PT_CONTINUE) failed with error %llX\n", res); + SendStatus(Sock, 0); + return; + } + + IsDebugging = true; + CurrentPID = pid; + + SendStatus(Sock, 1); +} + +void Debug::Detach(OrbisNetId Sock) +{ + auto pid = RecieveInt(Sock); + auto result = TryDetach(pid); + SendStatus(Sock, result ? 1 : 0); +} + Debug::Debug() { diff --git a/Playstation/OrbisLibAPI/Debug.h b/Playstation/OrbisLibAPI/Debug.h index 6f31133..94eeaab 100644 --- a/Playstation/OrbisLibAPI/Debug.h +++ b/Playstation/OrbisLibAPI/Debug.h @@ -3,12 +3,16 @@ class Debug { public: + bool IsDebugging; + int CurrentPID; + Debug(); ~Debug(); void HandleAPI(OrbisNetId Sock, APIPacket* Packet); private: - bool IsDebugging; - int CurrentPID; + bool TryDetach(int pid); + void Attach(OrbisNetId Sock); + void Detach(OrbisNetId Sock); }; diff --git a/Playstation/OrbisLibAPI/Proc.cpp b/Playstation/OrbisLibAPI/Proc.cpp index 53234ed..712b715 100644 --- a/Playstation/OrbisLibAPI/Proc.cpp +++ b/Playstation/OrbisLibAPI/Proc.cpp @@ -13,8 +13,6 @@ void Proc::HandleAPI(OrbisNetId Sock, APIPacket* Packet) SendProcessList(Sock); - SendStatus(Sock, APIResults::API_OK); - break; case API_PROC_LOAD_ELF: @@ -39,38 +37,31 @@ Proc::~Proc() void Proc::SendProcessList(OrbisNetId Sock) { - // TODO: Update // Allocate space for packet to send. - /*auto Packet = (ProcPacket*)malloc(sizeof(ProcPacket)); + auto Packet = (ProcPacket*)malloc(sizeof(ProcPacket)); - // Gets list of running processes. - auto procInfo = (ProcInfo*)malloc(sizeof(ProcInfo) * 200); - memset(procInfo, 0, sizeof(ProcInfo) * 200); - int ProcessCount = KDriver::GetProcessList(200, procInfo); + // Get the list of running processes. + std::vector processList; + GetProcessList(processList); - // Send the number of processes running. - sceNetSend(Sock, &ProcessCount, sizeof(int), 0); + SockSendInt(Sock, processList.size()); - // Populate each process packet and send it. - for (auto i = 0; i < ProcessCount; i++) + for (const auto& i : processList) { memset(Packet, 0, sizeof(ProcPacket)); - Packet->ProcessID = procInfo[i].PID; - Packet->Attached = procInfo[i].Attached; + // Get the app info using the pid. + OrbisAppInfo appInfo; + sceKernelGetAppInfo(i.pid, &appInfo); - strcpy(Packet->ProcName, procInfo[i].ProcName); - strcpy(Packet->TitleID, procInfo[i].TitleID); - - Packet->TextSegmentBase = procInfo[i].TextSegmentBase; - Packet->TextSegmentLen = procInfo[i].TextSegmentLen; - Packet->DataSegmentBase = procInfo[i].DataSegmentBase; - Packet->DataSegmentLen = procInfo[i].DataSegmentLen; + Packet->AppId = appInfo.AppId; + Packet->ProcessId = i.pid; + strcpy(Packet->Name, i.name); + strcpy(Packet->TitleId, appInfo.TitleId); sceNetSend(Sock, Packet, sizeof(ProcPacket), 0); } // Cleanup. free(Packet); - free(procInfo);*/ } \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/Target.cpp b/Playstation/OrbisLibAPI/Target.cpp index 34adad2..5ae2d69 100644 --- a/Playstation/OrbisLibAPI/Target.cpp +++ b/Playstation/OrbisLibAPI/Target.cpp @@ -1,6 +1,7 @@ #include "Common.h" #include "Target.h" #include "APIHelper.h" +#include "Debug.h" #include void Target::HandleAPI(OrbisNetId Sock, APIPacket* Packet) @@ -66,9 +67,9 @@ void Target::HandleAPI(OrbisNetId Sock, APIPacket* Packet) } } -Target::Target() +Target::Target(class Debug* Debug) { - + this->Debug = Debug; } Target::~Target() @@ -87,6 +88,7 @@ void Target::SendTargetInfo(OrbisNetId Sock) Packet->CPUTemp = GetCPUTemp(); Packet->SOCTemp = GetSOCTemp(); + // Current Big App. auto bigAppAppId = sceSystemServiceGetAppIdOfBigApp(); if (bigAppAppId > 0) { @@ -129,11 +131,14 @@ void Target::SendTargetInfo(OrbisNetId Sock) GetPSID(Packet->PSID); Packet->ConsoleType = GetConsoleType(); - // TODO: Debugging Added Later. - Packet->Attached = false; // TODO: Add funcionality. - //Packet->CurrentProc + // Debugging. + Packet->AttachedPid = Debug->CurrentPID; + Packet->Attached = Debug->IsDebugging; + // User. sceUserServiceGetForegroundUser(&Packet->ForegroundAccountId); + + // Storage Stats. auto res = ShellCoreUtil::sceShellCoreUtilGetFreeSizeOfUserPartition(&Packet->FreeSpace, &Packet->TotalSpace); // Perf Stats. TODO: Move from toolbox diff --git a/Playstation/OrbisLibAPI/Target.h b/Playstation/OrbisLibAPI/Target.h index 0b634e7..b03f491 100644 --- a/Playstation/OrbisLibAPI/Target.h +++ b/Playstation/OrbisLibAPI/Target.h @@ -1,9 +1,11 @@ #pragma once +class Debug; + class Target { public: - Target(); + Target(Debug* Debug); ~Target(); void HandleAPI(OrbisNetId Sock, APIPacket* Packet); @@ -12,5 +14,5 @@ public: void SetSettings(OrbisNetId Sock); private: - + Debug* Debug; }; \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/Utilities.cpp b/Playstation/OrbisLibAPI/Utilities.cpp index 740d13c..e01b496 100644 --- a/Playstation/OrbisLibAPI/Utilities.cpp +++ b/Playstation/OrbisLibAPI/Utilities.cpp @@ -202,6 +202,32 @@ bool SockRecvInt(OrbisNetId Sock, int* val) return !(sceNetRecv(Sock, val, sizeof(int), 0) < 0); } +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +bool SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen) +{ + unsigned char* CurrentPosition = data; + size_t DataLeft = dataLen; + int res = 0; + + while (DataLeft > 0) + { + size_t DataChunkSize = MIN(8192, DataLeft); + + res = sceNetSend(Sock, CurrentPosition, DataChunkSize, 0); + + if (res < 0) + { + return false; + } + + DataLeft -= res; + CurrentPosition += res; + } + + return true; +} + #pragma endregion void hexdump(void* ptr, int buflen) { diff --git a/Playstation/OrbisLibAPI/Utilities.h b/Playstation/OrbisLibAPI/Utilities.h index ec3ef9d..93e6918 100644 --- a/Playstation/OrbisLibAPI/Utilities.h +++ b/Playstation/OrbisLibAPI/Utilities.h @@ -15,9 +15,11 @@ bool Jailbreak(); bool CopySflash(); int getMacAddress(OrbisNetIfName ifName_Num, char* strOut, size_t strlen); +//TODO: Make socket class. // Networking bool SockSendInt(OrbisNetId Sock, int val); bool SockRecvInt(OrbisNetId Sock, int* val); +bool SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen); struct kinfo_proc { int structSize; //0x00 diff --git a/Playstation/OrbisLibAPI/Version.h b/Playstation/OrbisLibAPI/Version.h index e45173b..fea2b21 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 693 -#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 708 +#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/Playstation/OrbisLibAPI/main.cpp b/Playstation/OrbisLibAPI/main.cpp index 1a4761e..0ab3da1 100644 --- a/Playstation/OrbisLibAPI/main.cpp +++ b/Playstation/OrbisLibAPI/main.cpp @@ -84,7 +84,7 @@ int main() // Init App install utils. sceAppInstUtilInitialize(); -#define LOADTOOLBOX +//#define LOADTOOLBOX #ifdef LOADTOOLBOX auto handle = sys_sdk_proc_prx_load("SceShellUI", "/user/data/Orbis Toolbox/OrbisToolbox-2.0.sprx"); if (handle > 0) { diff --git a/Windows/Libraries/OrbisLib2/Common/API/API.cs b/Windows/Libraries/OrbisLib2/Common/API/API.cs index be81d65..2a7e289 100644 --- a/Windows/Libraries/OrbisLib2/Common/API/API.cs +++ b/Windows/Libraries/OrbisLib2/Common/API/API.cs @@ -2,6 +2,7 @@ using OrbisLib2.Common.Helpers; using OrbisLib2.Targets; using System.Net.Sockets; +using System.Runtime.InteropServices; namespace OrbisLib2.Common.API { @@ -81,6 +82,34 @@ namespace OrbisLib2.Common.API return (APIResults)Sock.RecvInt32(); } + /// + /// Recieves the next packet. + /// + /// The packet type. + /// Socket to recieve the packet on. + /// The packet to be recieved on. + /// Returns true if successful. + public static bool RecieveNextPacket(Socket Sock, ref T Packet) + { + try + { + var RawPacket = new byte[Marshal.SizeOf(Packet)]; + var bytes = Sock.Receive(RawPacket); + + if (bytes <= 0) + return false; + + // Convert the recieved bytes to a struct. + Helper.BytesToStruct(RawPacket, ref Packet); + + return true; + } + catch + { + return false; + } + } + /// /// /// diff --git a/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs b/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs index 0bd45bb..265f696 100644 --- a/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs +++ b/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs @@ -140,11 +140,12 @@ namespace OrbisLib2.Common.API [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)] public struct ProcPacket { - public int ProcessID; + public int AppId; + public int ProcessId; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string Name; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] - public string TitleID; + public string TitleId; } #endregion @@ -159,7 +160,7 @@ namespace OrbisLib2.Common.API STATE_SUSPENDED, }; - [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi), Serializable] + [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi, Size = 652), Serializable] public struct AppInfoPacket { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] diff --git a/Windows/Libraries/OrbisLib2/Common/Helpers/Helper.cs b/Windows/Libraries/OrbisLib2/Common/Helpers/Helper.cs index 5f40366..67864d4 100644 --- a/Windows/Libraries/OrbisLib2/Common/Helpers/Helper.cs +++ b/Windows/Libraries/OrbisLib2/Common/Helpers/Helper.cs @@ -1,8 +1,10 @@ -using System.Net.NetworkInformation; +using System.Data; +using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Text; +using static SQLite.SQLite3; namespace OrbisLib2.Common.Helpers { @@ -89,6 +91,21 @@ namespace OrbisLib2.Common.Helpers return BitConverter.ToInt32(Data, 0); } + public static void RecvLarge(this Socket s, byte[] data) + { + int Left = data.Length; + int Received = 0; + + while(Left > 0) + { + var chunkSize = Math.Min(s.ReceiveBufferSize, Left); + var res = s.Receive(data, Received, chunkSize, 0); + + Received += res; + Left -= res; + } + } + /// /// Easily connect to a socket and handle the time out. /// diff --git a/Windows/Libraries/OrbisLib2/Targets/Application.cs b/Windows/Libraries/OrbisLib2/Targets/Application.cs index 07dca9b..255dbda 100644 --- a/Windows/Libraries/OrbisLib2/Targets/Application.cs +++ b/Windows/Libraries/OrbisLib2/Targets/Application.cs @@ -1,5 +1,7 @@ using OrbisLib2.Common.API; using OrbisLib2.Common.Helpers; +using System.Data.Entity.Core.Metadata.Edm; +using System.Drawing; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; @@ -29,25 +31,25 @@ namespace OrbisLib2.Targets public List GetAppList() { var AppList = new List(); - var result = API.SendCommand(Target, 5, APICommands.API_APPS_GET_LIST, (Socket Sock, APIResults Result) => { // Get the number of apps installed. - int Count = Sock.RecvInt32(); + var Count = Sock.RecvInt32(); - // Itterate through the count to recieve all the apps details. - for (int i = 0; i < Count; i++) + // Recieve all of the arrary as one large packet. + var dataSize = Count * Marshal.SizeOf(typeof(AppInfoPacket)); + var data = new byte[dataSize]; + Sock.RecvLarge(data); + + // Allocate and copy the packet to begin marshaling it. + IntPtr ptr = Marshal.AllocHGlobal(dataSize); + Marshal.Copy(data, 0, ptr, dataSize); + + for(int i = 0; i < Count; i++) { - // Recieve the bytes of the struct. + // Marshal each part of the buffer to a struct. var Packet = new AppInfoPacket(); - var RawPacket = new byte[Marshal.SizeOf(Packet)]; - var bytes = Sock.Receive(RawPacket); - - if (bytes <= 0) - break; - - // Convert the recieved bytes to a struct. - Helper.BytesToStruct(RawPacket, ref Packet); + Packet = (AppInfoPacket)Marshal.PtrToStructure(IntPtr.Add(ptr, i * Marshal.SizeOf(typeof(AppInfoPacket))), typeof(AppInfoPacket)); // Try to parse the date time strings. if (!DateTime.TryParse(Packet.LastAccessTime, out DateTime LastAccessTime)) @@ -60,10 +62,11 @@ namespace OrbisLib2.Targets var firstNullIndex = Array.FindIndex(Packet.TitleName, b => b == 0); string titleName = Encoding.UTF8.GetString(Packet.TitleName, 0, firstNullIndex); - // Add the entry to the list. AppList.Add(new AppInfo(Packet.TitleId, Packet.ContentId, titleName, Packet.MetaDataPath, LastAccessTime, Packet.Visible, Packet.SortPriority, Packet.DispLocation, Packet.CanRemove == 1, Packet.Category, Packet.ContentSize, InstallDate, Packet.UICategory)); } + + Marshal.FreeHGlobal(ptr); }); return AppList; diff --git a/Windows/Libraries/OrbisLib2/Targets/Process.cs b/Windows/Libraries/OrbisLib2/Targets/Process.cs new file mode 100644 index 0000000..cf837c3 --- /dev/null +++ b/Windows/Libraries/OrbisLib2/Targets/Process.cs @@ -0,0 +1,42 @@ +using OrbisLib2.Common.API; +using OrbisLib2.Common.Helpers; +using System.Net.Sockets; +using System.Runtime.InteropServices; + +namespace OrbisLib2.Targets +{ + public record ProcInfo(int AppId, int ProcessId, string Name, string TitleId); + + public class Process + { + private Target Target; + + public Process(Target Target) + { + this.Target = Target; + } + + public List GetList() + { + var list = new List(); + + API.SendCommand(Target, 4, APICommands.API_PROC_GET_LIST, (Socket Sock, APIResults Result) => + { + var processCount = Sock.RecvInt32(); + + for(int i = 0; i < processCount; i++) + { + var Packet = new ProcPacket(); + if(!API.RecieveNextPacket(Sock, ref Packet)) + { + continue; + } + + list.Add(new ProcInfo(Packet.AppId, Packet.ProcessId, Packet.Name, Packet.TitleId)); + } + }); + + return list; + } + } +} diff --git a/Windows/Libraries/OrbisLib2/Targets/Target.cs b/Windows/Libraries/OrbisLib2/Targets/Target.cs index de7d1af..2ba89a7 100644 --- a/Windows/Libraries/OrbisLib2/Targets/Target.cs +++ b/Windows/Libraries/OrbisLib2/Targets/Target.cs @@ -83,7 +83,7 @@ namespace OrbisLib2.Targets public TargetEvents Events; // public Debug Debug; public Payload Payload; - // public Process Process; + public Process Process; public FTP FTP; public Application Application; @@ -94,7 +94,7 @@ namespace OrbisLib2.Targets Events = new TargetEvents(this); // Debug = new Debug(this); Payload = new Payload(this); - // Process = new Process(PS4, this); + Process = new Process(this); FTP = new FTP(this); Application = new Application(this); } diff --git a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs index db5ed77..1362f0a 100644 --- a/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs +++ b/Windows/OrbisNeighborHood/MVVM/View/AppListView.xaml.cs @@ -46,24 +46,24 @@ namespace OrbisNeighborHood.MVVM.View "CUSA01000" }; + private List PanelList = new List(); + public AppListView() { InitializeComponent(); Events.DBTouched += Events_DBTouched; Events.TargetStateChanged += Events_TargetStateChanged; + // TODO: add event for selected target changing. // Refresh the info about the current target. RefreshTargetInfo(); - Task.Run(() => - { - // Initially populate the app list. - InitAppList(); + // Set Item source for listbox. + AppList.ItemsSource = PanelList; - // Create task to periodically check for app.db changes. - // Task.Run(() => CheckAppDatabase()); - }); + // Create task to periodically check for app.db changes. + Task.Run(() => CheckAppDatabase()); } #region Properties @@ -110,95 +110,6 @@ namespace OrbisNeighborHood.MVVM.View #endregion - public void AddApp(string appCachePath, AppInfo App) - { - var currentTarget = TargetManager.SelectedTarget; - - // Make sure the titleId format is correct. Helps weed out bad entries and folders. - if (!Regex.IsMatch(App.TitleId, @"[a-zA-Z]{4}\d{5}")) - return; - - // Skip the Destiny entries that just exist for some reason even after a restore?... lol - if ((App.TitleId.Equals("CUSA00219") || App.TitleId.Equals("CUSA00568") || App.TitleId.Equals("CUSA01000")) && App.ContentSize <= 0) - return; - - // Skip some that aren't technically an app. - if (TitleIdExlusionList.Contains(App.TitleId)) - return; - - // Weed out some more bad entries created by default. - if (App.TitleName.Length <= 2) - return; - - // Make sure only add ones with a category. - if (App.UICategory.Length <= 0 || App.Category.Length <= 0) - return; - - // Directory to cache stuff for app. - string currentAppPath = Path.Combine(appCachePath, App.TitleId); - - // Create Directory for current app. - if (!Directory.Exists(currentAppPath)) - { - Directory.CreateDirectory(currentAppPath); - } - - // Cache icon0.png for app if we have not already. - if (!File.Exists(Path.Combine(currentAppPath, "icon0.png")) && !string.IsNullOrEmpty(App.MetaDataPath) && currentTarget.Info.IsAvailable) //TODO: Maybe add a isFTPAvailable. - { - currentTarget.FTP.DownloadFile($"{App.MetaDataPath}/icon0.png", Path.Combine(currentAppPath, "icon0.png")); - } - - // Fetch the App version. - var appVersion = currentTarget.Application.GetAppInfoString(App.TitleId, "APP_VER"); - - // Add or update app list item. - Dispatcher.Invoke(() => - { - var panel = AppList.Items.Cast().ToList().Find(x => x.App.TitleId == App.TitleId); - if (panel != null) - { - panel.Update(App, appVersion); - } - else - { - AppList.Items.Add(new AppPanel(App, appVersion)); - } - }); - } - - private void InitAppList() - { - // Clear lists so we can re-populate them. - Dispatcher.Invoke(() => AppList.Items.Clear()); - - // Make sure we have a target we can pull the db from. - if (TargetManager.Targets.Count <= 0) - return; - - // Make sure the Target is online so we can pull the db. - var currentTarget = TargetManager.SelectedTarget; - if (currentTarget == null) - { - Console.WriteLine("No current target we can use to load apps."); - return; - } - - // Make sure we have the appCache folder. - string appCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Orbis Suite\AppCache\"); - if (!Directory.Exists(appCachePath)) - { - Directory.CreateDirectory(appCachePath); - } - - var appList = currentTarget.Application.GetAppList(); - - Parallel.ForEach(appList, app => - { - AddApp(appCachePath, app); - }); - } - private async Task CheckAppDatabase() { while (true) @@ -216,30 +127,81 @@ namespace OrbisNeighborHood.MVVM.View continue; } - // Appcache location. - string appCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Orbis Suite\AppCache\"); - // Get the current app list. var appList = currentTarget.Application.GetAppList(); - // Check for deletions. - Parallel.ForEach(AppList.Items.Cast().ToList(), app => + // Check for adding apps. + Parallel.ForEach(appList, app => { - if (appList.Find(x => x.TitleId == app.App.TitleId) == null) + var currentTarget = TargetManager.SelectedTarget; + string appCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Orbis Suite\AppCache\"); + + // Make sure the titleId format is correct. Helps weed out bad entries and folders. + if (!Regex.IsMatch(app.TitleId, @"[a-zA-Z]{4}\d{5}")) + return; + + // Skip the Destiny entries that just exist for some reason even after a restore?... lol + if ((app.TitleId.Equals("CUSA00219") || app.TitleId.Equals("CUSA00568") || app.TitleId.Equals("CUSA01000")) && app.ContentSize <= 0) + return; + + // Skip some that aren't technically an app. + if (TitleIdExlusionList.Contains(app.TitleId)) + return; + + // Weed out some more bad entries created by default. + if (app.TitleName.Length <= 2) + return; + + // Make sure only add ones with a category. + if (app.UICategory.Length <= 0 || app.Category.Length <= 0) + return; + + // Directory to cache stuff for app. + string currentAppPath = Path.Combine(appCachePath, app.TitleId); + + // Create Directory for current app. + if (!Directory.Exists(currentAppPath)) { - Dispatcher.Invoke(() => AppList.Items.Remove(app)); + Directory.CreateDirectory(currentAppPath); + } + + // Cache icon0.png for app if we have not already. + if (!File.Exists(Path.Combine(currentAppPath, "icon0.png")) && !string.IsNullOrEmpty(app.MetaDataPath) && currentTarget.Info.IsAvailable) //TODO: Maybe add a isFTPAvailable. + { + currentTarget.FTP.DownloadFile($"{app.MetaDataPath}/icon0.png", Path.Combine(currentAppPath, "icon0.png")); + } + + // Fetch the App version. + var appVersion = currentTarget.Application.GetAppInfoString(app.TitleId, "APP_VER"); + + Dispatcher.Invoke(() => + { + var pannel = PanelList.Find(x => x.App.TitleId == app.TitleId); + if(pannel != null) + { + pannel.Update(app, appVersion); + } + else + { + PanelList.Add(new AppPanel(app, appVersion)); + } + }); + }); + + // Check to remove apps. + Parallel.ForEach(PanelList, panel => + { + var app = appList.Find(x => x.TitleId == panel.App.TitleId); + if(app == null) + { + PanelList.Remove(panel); } }); - // Check for new apps / updates. - Parallel.ForEach(appList, app => + // Update view. + Dispatcher.Invoke(() => { - var currentAppList = AppList.Items.Cast().ToList(); - - if (currentAppList.Find(x => x.App.TitleId == app.TitleId) == null) - { - AddApp(appCachePath, app); - } + AppList.Items.Refresh(); }); await Task.Delay(2000); diff --git a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt index 0bbd854..0b460a9 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt @@ -1 +1 @@ -2073 +2161 diff --git a/Windows/OrbisNeighborHood/Resources/BuildString.txt b/Windows/OrbisNeighborHood/Resources/BuildString.txt index 8350fab..d5b5301 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildString.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildString.txt @@ -1 +1 @@ -Version 3.0.2073 Debug Build Friday December 23 2022 11:44 PM +Version 3.0.2161 Debug Build Saturday December 24 2022 11:40 AM