Move to read db on console to reduce strain on the ftp.
This commit is contained in:
@@ -20,6 +20,8 @@ enum APICommands
|
||||
/* ####### Apps functions ####### */
|
||||
APP_START,
|
||||
|
||||
API_APPS_GET_LIST,
|
||||
API_APPS_GET_INFO_STR,
|
||||
API_APPS_STATUS,
|
||||
API_APPS_START,
|
||||
API_APPS_STOP,
|
||||
@@ -104,7 +106,6 @@ enum APICommands
|
||||
API_TARGET_SET_LED,
|
||||
API_TARGET_DUMP_PROC,
|
||||
API_TARGET_SET_SETTINGS,
|
||||
API_TARGET_GET_APPDB,
|
||||
API_TARGET_GETFILE,
|
||||
|
||||
TARGET_END,
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "Common.h"
|
||||
#include "AppDatabase.h"
|
||||
#include "sqlite3.h"
|
||||
|
||||
sqlite3* AppDatabase::OpenDatabase()
|
||||
{
|
||||
sqlite3* db;
|
||||
|
||||
auto res = sqlite3_open("/system_data/priv/mms/app.db", &db);
|
||||
if (res != SQLITE_OK)
|
||||
{
|
||||
klog("OpenDatabase(): Failed because %s\n", sqlite3_errmsg(db));
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return db;
|
||||
}
|
||||
}
|
||||
|
||||
const char* GetText(sqlite3_stmt* stmt, int column)
|
||||
{
|
||||
auto res = sqlite3_column_text(stmt, column);
|
||||
if (res != 0)
|
||||
{
|
||||
return (const char*)res;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool AppDatabase::GetApps(std::vector<AppInfo> &Apps)
|
||||
{
|
||||
int res;
|
||||
|
||||
auto db = OpenDatabase();
|
||||
if (db == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the current user id.
|
||||
int ForegroundAccountId;
|
||||
sceUserServiceGetForegroundUser(&ForegroundAccountId);
|
||||
|
||||
// build statement.
|
||||
char query[0x200];
|
||||
snprintf(query, sizeof(query), "SELECT * FROM tbl_appbrowse_0%i", ForegroundAccountId);
|
||||
|
||||
// Prepare statement.
|
||||
sqlite3_stmt* stmt;
|
||||
res = sqlite3_prepare(db, query, -1, &stmt, NULL);
|
||||
if (res != SQLITE_OK)
|
||||
{
|
||||
klog("sqlite3_prepare(): Failed because %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Execute step until all rows are read.
|
||||
while ((res = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
AppInfo info;
|
||||
strcpy(info.TitleId, GetText(stmt, 0));
|
||||
strcpy(info.ContentId, GetText(stmt, 1));
|
||||
strcpy(info.TitleName, GetText(stmt, 2));
|
||||
strcpy(info.MetaDataPath, GetText(stmt, 3));
|
||||
strcpy(info.LastAccessTime, GetText(stmt, 4));
|
||||
info.Visible = sqlite3_column_int(stmt, 8);
|
||||
info.SortPriority = sqlite3_column_int(stmt, 9);
|
||||
info.DispLocation = sqlite3_column_int(stmt, 12);
|
||||
info.CanRemove = sqlite3_column_int(stmt, 13) == 1;
|
||||
strcpy(info.Category, GetText(stmt, 14));
|
||||
info.ContentSize = sqlite3_column_int(stmt, 22);
|
||||
strcpy(info.InstallDate, GetText(stmt, 23));
|
||||
strcpy(info.UICategory, GetText(stmt, 25));
|
||||
|
||||
Apps.push_back(info);
|
||||
}
|
||||
|
||||
if (res != SQLITE_DONE) {
|
||||
printf("GetApps(): Res %d Error: %s\n", res, sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
// Release resources.
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AppDatabase::GetAppInfoString(const char* TitleId, char* Out, size_t OutSize, const char* Key)
|
||||
{
|
||||
int res;
|
||||
|
||||
auto db = OpenDatabase();
|
||||
if (db == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// build statement.
|
||||
char query[0x200];
|
||||
snprintf(query, sizeof(query), "SELECT * FROM tbl_appinfo WHERE titleId='%s' AND key='%s'", TitleId, Key);
|
||||
|
||||
// Prepare statement.
|
||||
sqlite3_stmt* stmt;
|
||||
res = sqlite3_prepare(db, query, -1, &stmt, NULL);
|
||||
if (res != SQLITE_OK)
|
||||
{
|
||||
klog("sqlite3_prepare(): Failed because %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = sqlite3_step(stmt);
|
||||
|
||||
if (res == SQLITE_ROW)
|
||||
{
|
||||
strlcpy(Out, GetText(stmt, 2), OutSize);
|
||||
|
||||
// Release resources.
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (res != SQLITE_DONE) {
|
||||
printf("GetApps(): Res %d Error: %s\n", res, sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
// Release resources.
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AppDatabase::SetVisibility(const char* TitleId, VisibilityType Visibility)
|
||||
{
|
||||
int res;
|
||||
|
||||
auto db = OpenDatabase();
|
||||
if (db == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the current user id.
|
||||
int ForegroundAccountId;
|
||||
sceUserServiceGetForegroundUser(&ForegroundAccountId);
|
||||
|
||||
// build statement.
|
||||
char query[0x200];
|
||||
snprintf(query, sizeof(query), "UPDATE tbl_appbrowse_0%i SET visible=%i WHERE titleId='%s'", ForegroundAccountId, Visibility, TitleId);
|
||||
|
||||
// Execute Statement.
|
||||
res = sqlite3_exec(db, query, nullptr, nullptr, nullptr);
|
||||
if (res != SQLITE_OK)
|
||||
{
|
||||
klog("sqlite3_exec(): Failed because %s\n", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Release resources.
|
||||
sqlite3_close(db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AppDatabase::AppDatabase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AppDatabase::~AppDatabase()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include "Common.h"
|
||||
#include "sqlite3.h"
|
||||
|
||||
class AppDatabase
|
||||
{
|
||||
public:
|
||||
enum VisibilityType
|
||||
{
|
||||
VT_NONE,
|
||||
VT_VISIBLE,
|
||||
VT_INVISIBLE,
|
||||
};
|
||||
|
||||
enum DispLocation
|
||||
{
|
||||
DL_NONE = 0,
|
||||
DL_CONTENTAREA = 1,
|
||||
DL_TV_VIDEO = 2,
|
||||
DL_LIBRARY = 4,
|
||||
DL_UNK = 5,
|
||||
};
|
||||
|
||||
struct AppInfo
|
||||
{
|
||||
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];
|
||||
};
|
||||
|
||||
static bool GetApps(std::vector<AppInfo> &Apps);
|
||||
static bool GetAppInfoString(const char* TitleId, char* Out, size_t OutSize, const char* Key);
|
||||
static bool SetVisibility(const char* TitleId, VisibilityType Visibility);
|
||||
|
||||
AppDatabase();
|
||||
~AppDatabase();
|
||||
|
||||
private:
|
||||
static sqlite3* OpenDatabase();
|
||||
};
|
||||
@@ -2,20 +2,38 @@
|
||||
#include "Apps.h"
|
||||
#include <orbis/SysCore.h>
|
||||
#include <orbis/SystemService.h>
|
||||
#include "AppDatabase.h"
|
||||
|
||||
void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet)
|
||||
{
|
||||
// Get the titleId of the App
|
||||
char titleId[9];
|
||||
sceNetRecv(Sock, titleId, sizeof(titleId), 0);
|
||||
char titleId[10];
|
||||
memset(titleId, 0, sizeof(titleId));
|
||||
|
||||
// For commands that need it get the titleId of the App
|
||||
if (Packet->Command > API_APPS_GET_LIST)
|
||||
{
|
||||
sceNetRecv(Sock, titleId, sizeof(titleId), 0);
|
||||
}
|
||||
|
||||
switch (Packet->Command)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case API_APPS_STATUS:
|
||||
case API_APPS_GET_LIST:
|
||||
|
||||
GetAppsList(Sock);
|
||||
|
||||
break;
|
||||
|
||||
case API_APPS_GET_INFO_STR:
|
||||
|
||||
GetAppInfoString(Sock, titleId);
|
||||
|
||||
break;
|
||||
|
||||
case API_APPS_STATUS:
|
||||
|
||||
SendAppStatus(Sock, titleId);
|
||||
|
||||
break;
|
||||
@@ -34,6 +52,45 @@ void Apps::HandleAPI(OrbisNetId Sock, APIPacket* Packet)
|
||||
}
|
||||
}
|
||||
|
||||
void Apps::GetAppsList(OrbisNetId Sock)
|
||||
{
|
||||
std::vector<AppDatabase::AppInfo> AppList;
|
||||
if (!AppDatabase::GetApps(AppList))
|
||||
{
|
||||
SockSendInt(Sock, 0);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void Apps::GetAppInfoString(OrbisNetId Sock, const char* TitleId)
|
||||
{
|
||||
// Get the key we are interested in.
|
||||
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)
|
||||
{
|
||||
int appId = 0;
|
||||
|
||||
@@ -11,6 +11,8 @@ public:
|
||||
void HandleAPI(OrbisNetId Sock, APIPacket* Packet);
|
||||
|
||||
private:
|
||||
void GetAppsList(OrbisNetId Sock);
|
||||
void GetAppInfoString(OrbisNetId Sock, const char* TitleId);
|
||||
void SendAppStatus(OrbisNetId Sock, const char* TitleId);
|
||||
void StartApp(OrbisNetId Sock, const char* TitleId);
|
||||
void KillApp(OrbisNetId Sock, const char* TitleId);
|
||||
|
||||
@@ -51,8 +51,8 @@ call build.bat $(IntDir) "$(TargetName)" "$(SolutionDir)"</NMakeReBuildCommandLi
|
||||
del /s /q /f $(IntDir)\*.elf
|
||||
del /s /q /f $(IntDir)\*.oelf</NMakeCleanCommandLine>
|
||||
<OutDir>$(SolutionDir)</OutDir>
|
||||
<NMakeIncludeSearchPath>$(OO_PS4_TOOLCHAIN)\include;External\GoldHEN_Plugins_SDK\include;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
|
||||
<IncludePath>E:\Greg\Repos\Orbis-Suite-3.0\External\GoldHEN_Plugins_SDK\include;$(IncludePath)</IncludePath>
|
||||
<NMakeIncludeSearchPath>$(OO_PS4_TOOLCHAIN)\include;External\GoldHEN_Plugins_SDK\include;External\LibSQLite-ps4\include;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
|
||||
<IncludePath>E:\Greg\Repos\Orbis-Suite-3.0\External\LibSQLite-ps4\include;E:\Greg\Repos\Orbis-Suite-3.0\External\GoldHEN_Plugins_SDK\include;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<NMakeOutput>eboot.bin</NMakeOutput>
|
||||
@@ -63,6 +63,7 @@ del /s /q /f $(IntDir)\*.oelf</NMakeCleanCommandLine>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="API.cpp" />
|
||||
<ClCompile Include="APIHelper.cpp" />
|
||||
<ClCompile Include="AppDatabase.cpp" />
|
||||
<ClCompile Include="Apps.cpp" />
|
||||
<ClCompile Include="Breakpoint.cpp" />
|
||||
<ClCompile Include="Debug.cpp" />
|
||||
@@ -81,9 +82,11 @@ del /s /q /f $(IntDir)\*.oelf</NMakeCleanCommandLine>
|
||||
<ClCompile Include="Watchpoint.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\External\LibSQLite-ps4\include\sqlite3.h" />
|
||||
<ClInclude Include="API.h" />
|
||||
<ClInclude Include="APIHelper.h" />
|
||||
<ClInclude Include="APIPackets.h" />
|
||||
<ClInclude Include="AppDatabase.h" />
|
||||
<ClInclude Include="Apps.h" />
|
||||
<ClInclude Include="Breakpoint.h" />
|
||||
<ClInclude Include="Common.h" />
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
<Filter Include="Header Files\Utilities\PS Utils">
|
||||
<UniqueIdentifier>{5094835e-2ace-4366-93ee-a65317ee8a62}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\SQLite">
|
||||
<UniqueIdentifier>{9184ee1e-6be1-4208-9c34-f2cca837b49f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="build.bat" />
|
||||
@@ -97,6 +100,9 @@
|
||||
<ClCompile Include="Apps.cpp">
|
||||
<Filter>Source Files\API\CmdGroups</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AppDatabase.cpp">
|
||||
<Filter>Source Files\Utilities\PS Utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Common.h">
|
||||
@@ -156,5 +162,11 @@
|
||||
<ClInclude Include="Apps.h">
|
||||
<Filter>Header Files\API\CmdGroups</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\External\LibSQLite-ps4\include\sqlite3.h">
|
||||
<Filter>Header Files\SQLite</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AppDatabase.h">
|
||||
<Filter>Header Files\Utilities\PS Utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -34,8 +34,8 @@ void* SocketListener::DoWork()
|
||||
// Make new TCP Socket
|
||||
this->Socket = sceNetSocket("Listener Socket", ORBIS_NET_AF_INET, ORBIS_NET_SOCK_STREAM, ORBIS_NET_IPPROTO_TCP);
|
||||
|
||||
// Set Sending and reciving time out to 1000 ms
|
||||
int sock_timeout = 10000;
|
||||
// Set Sending and reciving time out to 2s
|
||||
int sock_timeout = 2000000;
|
||||
sceNetSetsockopt(this->Socket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_SNDTIMEO, &sock_timeout, sizeof(sock_timeout));
|
||||
sceNetSetsockopt(this->Socket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_RCVTIMEO, &sock_timeout, sizeof(sock_timeout));
|
||||
|
||||
@@ -96,6 +96,10 @@ void* SocketListener::DoWork()
|
||||
int optval = 1;
|
||||
sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_NOSIGPIPE, &optval, sizeof(optval));
|
||||
|
||||
int sock_timeout = 2000000;
|
||||
sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_SNDTIMEO, &sock_timeout, sizeof(sock_timeout));
|
||||
sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_RCVTIMEO, &sock_timeout, sizeof(sock_timeout));
|
||||
|
||||
// Set up thread params.
|
||||
ClientThreadParams* Params = new ClientThreadParams();
|
||||
Params->socketListener = this;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
#define ORBISLIB_MAJOR 3
|
||||
#define ORBISLIB_MINOR 0
|
||||
#define ORBISLIB_BUILDVERSION 577
|
||||
#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 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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
SETLOCAL EnableDelayedExpansion
|
||||
|
||||
Rem Libraries to link in
|
||||
set libraries=-lc++ -lc -lSceSysModule -lkernel -lSceVideoOut -lSceSystemService -lSceSysCore -lSceSystemStateMgr -lSceNet -lScePad -lSceUserService -lSceRegMgr -lSceFreeType -lSceMsgDialog -lSceCommonDialog -lGoldHEN_Hook
|
||||
set libraries=-lc++ -lc -lSceSysModule -lkernel -lSceVideoOut -lSceSystemService -lSceSysCore -lSceSystemStateMgr -lSceNet -lScePad -lSceUserService -lSceRegMgr -lSceFreeType -lSceMsgDialog -lSceCommonDialog -lGoldHEN_Hook -lSQLite
|
||||
|
||||
Rem Read the script arguments into local vars
|
||||
set intdir=%1
|
||||
@@ -13,7 +13,7 @@ set outputOelf=%intdir%%targetname%.oelf
|
||||
|
||||
Rem Compile object files for all the source files
|
||||
for %%f in (*.cpp) do (
|
||||
clang++ -cc1 -triple x86_64-scei-ps4-elf -I"%OO_PS4_TOOLCHAIN%\\include" -I"%OO_PS4_TOOLCHAIN%\\include\\c++\\v1" -I"..\\..\\External\\GoldHEN_Plugins_SDK\\include" -I"..\\..\\External\\ps4-libjbc" -DORBISLIB_DEBUG -emit-obj -o %intdir%\%%~nf.o %%~nf.cpp
|
||||
clang++ -cc1 -triple x86_64-scei-ps4-elf -I"%OO_PS4_TOOLCHAIN%\\include" -I"%OO_PS4_TOOLCHAIN%\\include\\c++\\v1" -I"..\\..\\External\\GoldHEN_Plugins_SDK\\include" -I"..\\..\\External\\ps4-libjbc" -I"..\\..\\External\\LibSQLite-ps4\\include" -DORBISLIB_DEBUG -emit-obj -o %intdir%\%%~nf.o %%~nf.cpp
|
||||
)
|
||||
|
||||
Rem Get a list of object files for linking
|
||||
@@ -21,7 +21,7 @@ set obj_files=
|
||||
for %%f in (%1\\*.o) do set obj_files=!obj_files! .\%%f
|
||||
|
||||
Rem Link the input ELF
|
||||
ld.lld -m elf_x86_64 -pie --script "%OO_PS4_TOOLCHAIN%\link.x" --eh-frame-hdr -o "%outputElf%" "-L%OO_PS4_TOOLCHAIN%\\lib" "-L..\\..\\External\\GoldHEN_Plugins_SDK" %libraries% --verbose "%OO_PS4_TOOLCHAIN%\lib\crt1.o" %obj_files% "..\\..\\External\\ps4-libjbc\\jbc.o"
|
||||
ld.lld -m elf_x86_64 -pie --script "%OO_PS4_TOOLCHAIN%\link.x" --eh-frame-hdr -o "%outputElf%" "-L%OO_PS4_TOOLCHAIN%\\lib" "-L..\\..\\External\\GoldHEN_Plugins_SDK" "-L..\\..\\External\\LibSQLite-ps4" %libraries% --verbose "%OO_PS4_TOOLCHAIN%\lib\crt1.o" %obj_files% "..\\..\\External\\ps4-libjbc\\jbc.o"
|
||||
|
||||
Rem Create the eboot
|
||||
%OO_PS4_TOOLCHAIN%\bin\windows\create-fself.exe -in "%outputElf%" --out "%outputOelf%" --eboot "eboot.bin" --paid 0x3800000000010003
|
||||
|
||||
@@ -2,11 +2,8 @@
|
||||
#include "Version.h"
|
||||
#include "API.h"
|
||||
#include "GoldHEN.h"
|
||||
#include <orbis/SystemService.h>
|
||||
#include <orbis/SysCore.h>
|
||||
#include <orbis/libkernel.h>
|
||||
#include <orbis/Net.h>
|
||||
#include <orbis/AppInstUtil.h>
|
||||
#include "AppDatabase.h"
|
||||
|
||||
#include "GeneralIPC.h"
|
||||
|
||||
|
||||
@@ -4,12 +4,17 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OrbisSuite
|
||||
{
|
||||
public record AppInfo(string TitleId, string ContentId, string TitleName, string MetaDataPath, DateTime LastAccessTime,
|
||||
int Visible, int SortPriority, int DisplayLocation, bool CanRemove, string Category, int ContentSize, DateTime InstallDate, string UICategory);
|
||||
|
||||
public class Application
|
||||
{
|
||||
private Target Target;
|
||||
@@ -19,6 +24,95 @@ namespace OrbisSuite
|
||||
this.Target = Target;
|
||||
}
|
||||
|
||||
public List<AppInfo> GetAppList()
|
||||
{
|
||||
var AppList = new List<AppInfo>();
|
||||
|
||||
// Check to see the API is online.
|
||||
if (!Target.Info.Details.IsAPIAvailable)
|
||||
{
|
||||
return AppList;
|
||||
}
|
||||
|
||||
// Make the initial request.
|
||||
APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_GET_LIST }, out Socket Sock);
|
||||
|
||||
// Make sure the request was sucessful.
|
||||
if (apiResult != APIResults.API_OK)
|
||||
return AppList;
|
||||
|
||||
// Get the number of apps installed.
|
||||
int Count = Sock.RecvInt32();
|
||||
|
||||
// Itterate through the count to recieve all the apps details.
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
// Recieve the bytes of the 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.
|
||||
Helpers.BytestoStruct(RawPacket, ref Packet);
|
||||
|
||||
// Try to parse the date time strings.
|
||||
if (!DateTime.TryParse(Packet.LastAccessTime, out DateTime LastAccessTime))
|
||||
LastAccessTime = DateTime.MinValue;
|
||||
|
||||
if (!DateTime.TryParse(Packet.LastAccessTime, out DateTime InstallDate))
|
||||
InstallDate = DateTime.MinValue;
|
||||
|
||||
// For some reason there is garbage after the string so this stops that :)
|
||||
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));
|
||||
}
|
||||
|
||||
// close socket.
|
||||
Sock.Close();
|
||||
|
||||
return AppList;
|
||||
}
|
||||
|
||||
public string GetAppInfoString(string TitleId, string Key)
|
||||
{
|
||||
if (!Regex.IsMatch(TitleId, @"[a-zA-Z]{4}\d{5}"))
|
||||
{
|
||||
Console.WriteLine($"Invaild titleId format {TitleId}");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (!Target.Info.Details.IsAPIAvailable)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_GET_INFO_STR }, out Socket Sock);
|
||||
|
||||
if (apiResult != APIResults.API_OK)
|
||||
return string.Empty;
|
||||
|
||||
// Send the titleId of the app.
|
||||
Sock.Send(Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray());
|
||||
|
||||
// Send the bytes of the key string.
|
||||
Sock.Send(Encoding.ASCII.GetBytes(Key.PadRight(50, '\0')));
|
||||
|
||||
var resultBuffer = new byte[200];
|
||||
Sock.Receive(resultBuffer);
|
||||
|
||||
// close socket.
|
||||
Sock.Close();
|
||||
|
||||
return Encoding.ASCII.GetString(resultBuffer);
|
||||
}
|
||||
|
||||
public AppState GetAppState(string TitleId)
|
||||
{
|
||||
if (!Regex.IsMatch(TitleId, @"[a-zA-Z]{4}\d{5}"))
|
||||
@@ -32,13 +126,13 @@ namespace OrbisSuite
|
||||
return AppState.STATE_NOT_RUNNING;
|
||||
}
|
||||
|
||||
APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APP_STATUS }, out Socket Sock);
|
||||
APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_STATUS }, out Socket Sock);
|
||||
|
||||
if (apiResult != APIResults.API_OK)
|
||||
return AppState.STATE_ERROR;
|
||||
|
||||
// Send the titleId of the app.
|
||||
var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(9, '\0')).Take(9).ToArray();
|
||||
var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray();
|
||||
Sock.Send(bytes);
|
||||
|
||||
// Get the state from API.
|
||||
@@ -63,13 +157,13 @@ namespace OrbisSuite
|
||||
return false;
|
||||
}
|
||||
|
||||
APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APP_START }, out Socket Sock);
|
||||
APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APPS_START }, out Socket Sock);
|
||||
|
||||
if (apiResult != APIResults.API_OK)
|
||||
return false;
|
||||
|
||||
// Send the titleId of the app.
|
||||
var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(9, '\0')).Take(9).ToArray();
|
||||
var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray();
|
||||
Sock.Send(bytes);
|
||||
|
||||
// Get the state from API.
|
||||
@@ -94,13 +188,13 @@ namespace OrbisSuite
|
||||
return false;
|
||||
}
|
||||
|
||||
APIResults apiResult = API.CallLong(Target.Info.IPAddress, Settings.CreateInstance().APIPort, new APIPacket() { PacketVersion = Config.PacketVersion, Command = APICommands.API_APP_STOP }, out Socket Sock);
|
||||
APIResults 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(9, '\0')).Take(9).ToArray();
|
||||
var bytes = Encoding.ASCII.GetBytes(TitleId.PadRight(10, '\0')).Take(10).ToArray();
|
||||
Sock.Send(bytes);
|
||||
|
||||
// Get the state from API.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace OrbisSuite.Common
|
||||
{
|
||||
@@ -17,12 +18,14 @@ namespace OrbisSuite.Common
|
||||
/* ####### Apps functions ####### */
|
||||
APP_START,
|
||||
|
||||
API_APP_STATUS,
|
||||
API_APP_START,
|
||||
API_APP_STOP,
|
||||
API_APP_SUSPEND,
|
||||
API_APP_RESUME,
|
||||
API_APP_DELETE,
|
||||
API_APPS_GET_LIST,
|
||||
API_APPS_GET_INFO_STR,
|
||||
API_APPS_STATUS,
|
||||
API_APPS_START,
|
||||
API_APPS_STOP,
|
||||
API_APPS_SUSPEND,
|
||||
API_APPS_RESUME,
|
||||
API_APPS_DELETE,
|
||||
|
||||
APP_END,
|
||||
/* ############################## */
|
||||
@@ -101,7 +104,6 @@ namespace OrbisSuite.Common
|
||||
API_TARGET_SET_LED,
|
||||
API_TARGET_DUMP_PROC,
|
||||
API_TARGET_SET_SETTINGS,
|
||||
API_TARGET_GET_APPDB,
|
||||
API_TARGET_GETFILE,
|
||||
|
||||
TARGET_END,
|
||||
@@ -158,6 +160,32 @@ namespace OrbisSuite.Common
|
||||
STATE_SUSPENDED,
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi), Serializable]
|
||||
public struct AppInfoPacket
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
|
||||
public string TitleId;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
|
||||
public string ContentId;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)]
|
||||
public byte[] TitleName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
|
||||
public string MetaDataPath;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
|
||||
public string LastAccessTime;
|
||||
public int Visible;
|
||||
public int SortPriority;
|
||||
public int DispLocation;
|
||||
public char CanRemove;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
|
||||
public string Category;
|
||||
public int ContentSize;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
|
||||
public string InstallDate;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
|
||||
public string UICategory;
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Debug
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
using SQLite;
|
||||
using System.Data;
|
||||
|
||||
namespace OrbisSuite.Common.Database.App
|
||||
{
|
||||
public class Master
|
||||
{
|
||||
public string type { get; set; }
|
||||
|
||||
public string name { get; set; }
|
||||
|
||||
public string tbl_name { get; set; }
|
||||
|
||||
public int rootpage { get; set; }
|
||||
|
||||
public string sql { get; set; }
|
||||
}
|
||||
|
||||
[Table("tbl_appbrowse")]
|
||||
public class AppBrowse
|
||||
{
|
||||
[PrimaryKey, NotNull]
|
||||
public string titleId { get; set; } = "";
|
||||
|
||||
public string contentId { get; set; } = "";
|
||||
|
||||
public string titleName { get; set; } = "";
|
||||
|
||||
public string metaDataPath { get; set; } = "";
|
||||
|
||||
public int visible { get; set; } = 0;
|
||||
|
||||
public int sortPriority { get; set; } = 0;
|
||||
|
||||
public int dispLocation { get; set; } = 0;
|
||||
|
||||
public int canRemove { get; set; } = 0;
|
||||
|
||||
public string category { get; set; } = "";
|
||||
|
||||
public int contentSize { get; set; } = 0;
|
||||
|
||||
public string installDate { get; set; } = "";
|
||||
|
||||
public string uiCategory { get; set; } = "";
|
||||
|
||||
public static bool AppBrowseRemoveUserId(string dbPath, int UserId)
|
||||
{
|
||||
var db = new SQLiteConnection(dbPath);
|
||||
|
||||
// List all of the tables in this data base.
|
||||
var dbList = db.Query<Master>("SELECT name FROM sqlite_master WHERE type = 'table'");
|
||||
|
||||
// Make sure we got some tables back.
|
||||
if (dbList.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// The name of the table with the user id appended to the end.
|
||||
var tableName = $"tbl_appbrowse_{UserId.ToString().PadLeft(10, '0')}";
|
||||
|
||||
// Search for the table we want to rename to not have the userId on the end.
|
||||
var appBrowseTable = dbList.Find(e => e.name.Equals(tableName))?.name;
|
||||
|
||||
// Make sure we found a table matching our pattern.
|
||||
if (appBrowseTable != null)
|
||||
{
|
||||
// Make sure we haven't already renamed this table.
|
||||
if (appBrowseTable.Equals("tbl_appbrowse"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rename it so we can use it.
|
||||
var result = db.Execute($"ALTER TABLE `{appBrowseTable}` RENAME TO `tbl_appbrowse`") > 0;
|
||||
db.Close();
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static bool AppBrowseAddUserId(string dbPath, int UserId)
|
||||
{
|
||||
var db = new SQLiteConnection(dbPath);
|
||||
|
||||
// The name of the table with the user id appended to the end.
|
||||
var tableName = $"tbl_appbrowse_{UserId.ToString().PadLeft(10, '0')}";
|
||||
|
||||
// Rename it so we can use it.
|
||||
var result = db.Execute($"ALTER TABLE `tbl_appbrowse` RENAME TO `{tableName}`") > 0;
|
||||
db.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<AppBrowse> GetAppBrowseList(string dbPath)
|
||||
{
|
||||
var db = new SQLiteConnection(dbPath);
|
||||
var result = db.Table<AppBrowse>().ToList();
|
||||
db.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*public static bool Save(string dbPath)
|
||||
{
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using SQLite;
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace OrbisSuite.Common.Database.App
|
||||
{
|
||||
[Table("tbl_version")]
|
||||
public class AppBrowseVersion
|
||||
{
|
||||
[PrimaryKey, NotNull]
|
||||
public string category { get; set; } = "";
|
||||
|
||||
public int status { get; set; }
|
||||
|
||||
public static int GetAppBrowseVersion(string DataBasePath)
|
||||
{
|
||||
var db = new SQLiteConnection(DataBasePath);
|
||||
|
||||
var result = db.Find((Expression<Func<AppBrowseVersion, bool>>)(x => x.category.Equals("sync_server")));
|
||||
db.Close();
|
||||
if(result != null)
|
||||
{
|
||||
return result.status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using SQLite;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace OrbisSuite.Common.Database.App
|
||||
{
|
||||
[Table("tbl_appinfo")]
|
||||
public class AppInfo
|
||||
{
|
||||
[PrimaryKey, NotNull]
|
||||
public string titleId { get; set; } = "";
|
||||
|
||||
[PrimaryKey, NotNull]
|
||||
public string key { get; set; } = "";
|
||||
|
||||
public string val { get; set; }
|
||||
|
||||
public static string GetStringFromAppInfo(string DataBasePath, string TitleId, string Key)
|
||||
{
|
||||
var db = new SQLiteConnection(DataBasePath);
|
||||
|
||||
var result = db.Find((Expression<Func<AppInfo, bool>>)(x => x.titleId.Equals(TitleId) && x.key.Equals(Key)));
|
||||
db.Close();
|
||||
if (result != null)
|
||||
{
|
||||
return result.val;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
using OrbisSuite;
|
||||
using OrbisSuite.Common;
|
||||
using OrbisSuite.Common.Database.App;
|
||||
using SimpleUI.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace OrbisNeighborHood.Controls
|
||||
{
|
||||
@@ -27,11 +15,11 @@ namespace OrbisNeighborHood.Controls
|
||||
/// </summary>
|
||||
public partial class AppPanel : UserControl
|
||||
{
|
||||
public AppBrowse App;
|
||||
public AppInfo App;
|
||||
|
||||
private AppState AppState = AppState.STATE_NOT_RUNNING;
|
||||
|
||||
public AppPanel(AppBrowse App, string AppVersion)
|
||||
public AppPanel(AppInfo App, string AppVersion)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
@@ -44,17 +32,17 @@ namespace OrbisNeighborHood.Controls
|
||||
Task.Run(() => UpdateApp());
|
||||
}
|
||||
|
||||
public void Update(AppBrowse App, string AppVersion)
|
||||
public void Update(AppInfo App, string AppVersion)
|
||||
{
|
||||
// Set the Info about this application.
|
||||
ApplicationNameElement.Text = App.titleName;
|
||||
TitleIdElement.FieldText = App.titleId;
|
||||
ApplicationNameElement.Text = App.TitleName;
|
||||
TitleIdElement.FieldText = App.TitleId;
|
||||
VersionElement.FieldText = AppVersion.TrimStart('0');
|
||||
TypeElement.FieldText = $"{App.uiCategory} ({App.category})";
|
||||
SizeElement.FieldText = App.contentSize <= 0 ? "N/A" : Utilities.BytesToString(App.contentSize);
|
||||
TypeElement.FieldText = $"{App.UICategory} ({App.Category})";
|
||||
SizeElement.FieldText = App.ContentSize <= 0 ? "N/A" : Utilities.BytesToString(App.ContentSize);
|
||||
|
||||
// Get the path to our icon and make sure it exists.
|
||||
string iconPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}\Orbis Suite\AppCache\{OrbisLib.Instance.SelectedTarget.Info.Details.ForegroundAccountId.ToString("X")}\{App.titleId}\icon0.png";
|
||||
string iconPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}\Orbis Suite\AppCache\{App.TitleId}\icon0.png";
|
||||
if(!string.IsNullOrEmpty(iconPath) && File.Exists(iconPath) && new FileInfo(iconPath).Length > 0)
|
||||
{
|
||||
// Load and cache image in memory.
|
||||
@@ -68,17 +56,14 @@ namespace OrbisNeighborHood.Controls
|
||||
IconImage.Source = image;
|
||||
}
|
||||
|
||||
if (DateTime.TryParse(App.installDate, out var dateTime))
|
||||
{
|
||||
InstallDateElement.FieldText = dateTime.ToString("ddd dd MMM yyy hh:mm tt");
|
||||
}
|
||||
InstallDateElement.FieldText = App.InstallDate.ToString("ddd dd MMM yyy hh:mm tt");
|
||||
|
||||
// Set the tool tips.
|
||||
StartStop.ToolTip = $"Start {App.titleName}.";
|
||||
Visibility.ToolTip = $"Hide {App.titleName} from Home Menu.";
|
||||
ChangeIcon.ToolTip = $"Change the icon of {App.titleName}.";
|
||||
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.
|
||||
Delete.ToolTip = $"Delete {App.titleName}.";
|
||||
Delete.ToolTip = $"Delete {App.TitleName}.";
|
||||
}
|
||||
|
||||
private void UpdateApp()
|
||||
@@ -88,30 +73,30 @@ namespace OrbisNeighborHood.Controls
|
||||
var currentTarget = OrbisLib.Instance.SelectedTarget;
|
||||
|
||||
// Get Current App status.
|
||||
var newAppState = currentTarget.Application.GetAppState(App.titleId);
|
||||
var newAppState = currentTarget.Application.GetAppState(App.TitleId);
|
||||
if (newAppState >= 0)
|
||||
AppState = newAppState;
|
||||
|
||||
// App status.
|
||||
if (AppState == AppState.STATE_RUNNING || AppState == AppState.STATE_SUSPENDED)
|
||||
{
|
||||
Dispatcher.Invoke(() => StartStop.ToolTip = $"Stop {App.titleName}.");
|
||||
Dispatcher.Invoke(() => StartStop.ToolTip = $"Stop {App.TitleName}.");
|
||||
Dispatcher.Invoke(() => StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Stop.png");
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispatcher.Invoke(() => StartStop.ToolTip = $"Start {App.titleName}.");
|
||||
Dispatcher.Invoke(() => StartStop.ToolTip = $"Start {App.TitleName}.");
|
||||
Dispatcher.Invoke(() => StartStop.ImageSource = "/OrbisNeighborHood;component/Images/Start.png");
|
||||
}
|
||||
|
||||
// App Visibility.
|
||||
if (App.visible == 0 || App.visible == 2)
|
||||
if (App.Visible == 0 || App.Visible == 2)
|
||||
{
|
||||
Dispatcher.Invoke(() => Visibility.ToolTip = $"Show {App.titleName} from Home Menu.");
|
||||
Dispatcher.Invoke(() => Visibility.ToolTip = $"Show {App.TitleName} from Home Menu.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Dispatcher.Invoke(() => Visibility.ToolTip = $"Hide {App.titleName} from Home Menu.");
|
||||
Dispatcher.Invoke(() => Visibility.ToolTip = $"Hide {App.TitleName} from Home Menu.");
|
||||
}
|
||||
|
||||
Thread.Sleep(1000);
|
||||
@@ -127,11 +112,11 @@ namespace OrbisNeighborHood.Controls
|
||||
var currentTarget = OrbisLib.Instance.SelectedTarget;
|
||||
if (AppState == AppState.STATE_RUNNING || AppState == AppState.STATE_SUSPENDED)
|
||||
{
|
||||
currentTarget.Application.Stop(App.titleId);
|
||||
currentTarget.Application.Stop(App.TitleId);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentTarget.Application.Start(App.titleId);
|
||||
currentTarget.Application.Start(App.TitleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using OrbisSuite.Common.Database.App;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
@@ -18,10 +17,6 @@ namespace OrbisNeighborHood.MVVM.View
|
||||
/// </summary>
|
||||
public partial class AppListView : UserControl
|
||||
{
|
||||
private static string _AppDatabaseRemotePath = @"/system_data/priv/mms/app.db";
|
||||
|
||||
private static Mutex appDataBaseMtx = new Mutex();
|
||||
|
||||
private static readonly List<string> TitleIdExlusionList = new List<string>()
|
||||
{
|
||||
"NPXS20108",
|
||||
@@ -38,6 +33,10 @@ namespace OrbisNeighborHood.MVVM.View
|
||||
"NPXS20106",
|
||||
"NPXS20114",
|
||||
"NPXS20120",
|
||||
"NPXS20109",
|
||||
"NPXS20112",
|
||||
"NPXS20133",
|
||||
"NPXS20132",
|
||||
|
||||
// Destiny? lol
|
||||
"CUSA00219",
|
||||
@@ -55,8 +54,14 @@ namespace OrbisNeighborHood.MVVM.View
|
||||
// Refresh the info about the current target.
|
||||
RefreshTargetInfo();
|
||||
|
||||
// Create task to periodically check for app.db changes.
|
||||
Task.Run(() => CheckAppDatabase());
|
||||
Task.Run(() =>
|
||||
{
|
||||
// Initially populate the app list.
|
||||
InitAppList();
|
||||
|
||||
// Create task to periodically check for app.db changes.
|
||||
// Task.Run(() => CheckAppDatabase());
|
||||
});
|
||||
}
|
||||
|
||||
#region Properties
|
||||
@@ -103,32 +108,32 @@ namespace OrbisNeighborHood.MVVM.View
|
||||
|
||||
#endregion
|
||||
|
||||
public void AddApp(string UserDirectoryPath, string AppVersion, AppBrowse App)
|
||||
public void AddApp(string appCachePath, AppInfo App)
|
||||
{
|
||||
var currentTarget = OrbisLib.Instance.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}"))
|
||||
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)
|
||||
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))
|
||||
if (TitleIdExlusionList.Contains(App.TitleId))
|
||||
return;
|
||||
|
||||
// Weed out some more bad entries created by default.
|
||||
if (App.titleName.Length <= 2)
|
||||
if (App.TitleName.Length <= 2)
|
||||
return;
|
||||
|
||||
// Make sure only add ones with a category.
|
||||
if (App.uiCategory.Length <= 0 || App.category.Length <= 0)
|
||||
if (App.UICategory.Length <= 0 || App.Category.Length <= 0)
|
||||
return;
|
||||
|
||||
// Directory to cache stuff for app.
|
||||
string currentAppPath = Path.Combine(UserDirectoryPath, App.titleId);
|
||||
string currentAppPath = Path.Combine(appCachePath, App.TitleId);
|
||||
|
||||
// Create Directory for current app.
|
||||
if (!Directory.Exists(currentAppPath))
|
||||
@@ -137,27 +142,30 @@ namespace OrbisNeighborHood.MVVM.View
|
||||
}
|
||||
|
||||
// Cache icon0.png for app if we have not already.
|
||||
if (!File.Exists(Path.Combine(currentAppPath, "icon0.png")) && !string.IsNullOrEmpty(App.metaDataPath) && currentTarget.Info.Details.IsAvailable) //TODO: Maybe add a isFTPAvailable.
|
||||
if (!File.Exists(Path.Combine(currentAppPath, "icon0.png")) && !string.IsNullOrEmpty(App.MetaDataPath) && currentTarget.Info.Details.IsAvailable) //TODO: Maybe add a isFTPAvailable.
|
||||
{
|
||||
currentTarget.FTP.DownloadFile($"{App.metaDataPath}/icon0.png", Path.Combine(currentAppPath, "icon0.png"));
|
||||
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<AppPanel>().ToList().Find(x => x.App.titleId == App.titleId);
|
||||
var panel = AppList.Items.Cast<AppPanel>().ToList().Find(x => x.App.TitleId == App.TitleId);
|
||||
if (panel != null)
|
||||
{
|
||||
panel.Update(App, AppVersion);
|
||||
panel.Update(App, appVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppList.Items.Add(new AppPanel(App, AppVersion));
|
||||
AppList.Items.Add(new AppPanel(App, appVersion));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task InitAppList()
|
||||
private void InitAppList()
|
||||
{
|
||||
// Clear lists so we can re-populate them.
|
||||
Dispatcher.Invoke(() => AppList.Items.Clear());
|
||||
@@ -181,48 +189,19 @@ namespace OrbisNeighborHood.MVVM.View
|
||||
Directory.CreateDirectory(appCachePath);
|
||||
}
|
||||
|
||||
// Path where we will store this data.
|
||||
var ForegroundAccountId = currentTarget.Info.Details.ForegroundAccountId;
|
||||
string userDirectoryPath = Path.Combine(appCachePath, ForegroundAccountId.ToString("X"));
|
||||
|
||||
// Create Directory for database.
|
||||
if (!Directory.Exists(userDirectoryPath))
|
||||
{
|
||||
Directory.CreateDirectory(userDirectoryPath);
|
||||
}
|
||||
|
||||
// Check to see if we have a database.
|
||||
string appDataBasePath = Path.Combine(userDirectoryPath, "app.db");
|
||||
if (!File.Exists(appDataBasePath))
|
||||
{
|
||||
Console.WriteLine("No app.db is cached.");
|
||||
return;
|
||||
}
|
||||
|
||||
appDataBaseMtx.WaitOne();
|
||||
|
||||
// Rename the table we need in the app.db.
|
||||
AppBrowse.AppBrowseRemoveUserId(appDataBasePath, ForegroundAccountId);
|
||||
|
||||
// Get all apps from the app.db
|
||||
var appList = AppBrowse.GetAppBrowseList(appDataBasePath);
|
||||
var appList = currentTarget.Application.GetAppList();
|
||||
|
||||
foreach (var app in appList)
|
||||
{
|
||||
Parallel.Invoke(() =>
|
||||
{
|
||||
AddApp(userDirectoryPath, AppInfo.GetStringFromAppInfo(appDataBasePath, app.titleId, "APP_VER"), app);
|
||||
AddApp(appCachePath, app);
|
||||
});
|
||||
}
|
||||
|
||||
appDataBaseMtx.ReleaseMutex();
|
||||
}
|
||||
|
||||
private async Task CheckAppDatabase()
|
||||
{
|
||||
// Update the current App list. Called here because it must be initialized before the update is called.
|
||||
await InitAppList();
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
@@ -238,75 +217,30 @@ namespace OrbisNeighborHood.MVVM.View
|
||||
continue;
|
||||
}
|
||||
|
||||
// Path where we will store this data.
|
||||
var ForegroundAccountId = currentTarget.Info.Details.ForegroundAccountId;
|
||||
string userDirectoryPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Orbis Suite\AppCache\", ForegroundAccountId.ToString("X"));
|
||||
// Appcache location.
|
||||
string appCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Orbis Suite\AppCache\");
|
||||
|
||||
// Download database.
|
||||
string appDataBasePath = Path.Combine(userDirectoryPath, "app.db");
|
||||
if (File.Exists(appDataBasePath))
|
||||
// Get the current app list.
|
||||
var appList = currentTarget.Application.GetAppList();
|
||||
|
||||
// Check for deletions.
|
||||
foreach (var app in AppList.Items.Cast<AppPanel>().ToList())
|
||||
{
|
||||
// Download the new app.db.
|
||||
string newAppDataBasePath = Path.Combine(userDirectoryPath, "new_app.db");
|
||||
if (currentTarget.FTP.DownloadFile(_AppDatabaseRemotePath, newAppDataBasePath))
|
||||
if (appList.Find(x => x.TitleId == app.App.TitleId) == null)
|
||||
{
|
||||
// Get app.db versions.
|
||||
var newVersion = AppBrowseVersion.GetAppBrowseVersion(newAppDataBasePath);
|
||||
var oldVersion = AppBrowseVersion.GetAppBrowseVersion(appDataBasePath);
|
||||
|
||||
// Compare the app.db versions.
|
||||
if (newVersion > oldVersion)
|
||||
{
|
||||
appDataBaseMtx.WaitOne();
|
||||
|
||||
// Remove the out dated database.
|
||||
File.Delete(appDataBasePath);
|
||||
|
||||
// Rename the new database.
|
||||
File.Move(newAppDataBasePath, appDataBasePath);
|
||||
|
||||
// Rename the table we need in the app.db.
|
||||
AppBrowse.AppBrowseRemoveUserId(appDataBasePath, ForegroundAccountId);
|
||||
|
||||
// Get all apps from the app.db
|
||||
var appList = AppBrowse.GetAppBrowseList(appDataBasePath);
|
||||
|
||||
// Check for deletions.
|
||||
foreach (var app in AppList.Items.Cast<AppPanel>().ToList())
|
||||
{
|
||||
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.Invoke(() =>
|
||||
{
|
||||
AddApp(userDirectoryPath, AppInfo.GetStringFromAppInfo(appDataBasePath, app.titleId, "APP_VER"), app);
|
||||
});
|
||||
}
|
||||
|
||||
appDataBaseMtx.ReleaseMutex();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove new database as ours is current.
|
||||
File.Delete(newAppDataBasePath);
|
||||
}
|
||||
Dispatcher.Invoke(() => AppList.Items.Remove(app));
|
||||
}
|
||||
}
|
||||
else if (currentTarget.Info.Details.IsAvailable)
|
||||
|
||||
// Check for new apps / updates.
|
||||
foreach (var app in appList)
|
||||
{
|
||||
// Download the app database for the first time.
|
||||
if (OrbisLib.Instance.SelectedTarget.FTP.DownloadFile(_AppDatabaseRemotePath, appDataBasePath))
|
||||
Parallel.Invoke(() =>
|
||||
{
|
||||
// Initialize the Application List now that we have an app.db.
|
||||
InitAppList();
|
||||
}
|
||||
AddApp(appCachePath, app);
|
||||
});
|
||||
}
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -1 +1 @@
|
||||
1856
|
||||
1956
|
||||
|
||||
@@ -1 +1 @@
|
||||
Version 3.0.1856 Debug Build Saturday December 17 2022 6:19 PM
|
||||
Version 3.0.1956 Debug Build Sunday December 18 2022 7:40 PM
|
||||
|
||||
Reference in New Issue
Block a user