add ability to view remote image file
This commit is contained in:
@@ -52,6 +52,7 @@ add_executable(ezremote_client
|
||||
source/main.cpp
|
||||
source/orbis_jbc.c
|
||||
source/system.cpp
|
||||
source/sfo.cpp
|
||||
source/textures.cpp
|
||||
source/windows.cpp
|
||||
source/zip_util.cpp
|
||||
|
||||
+4
-1
@@ -53,7 +53,10 @@ enum ACTIONS
|
||||
ACTION_NEW_REMOTE_FILE,
|
||||
ACTION_SET_DEFAULT_LOCAL_FOLDER,
|
||||
ACTION_SET_DEFAULT_REMOTE_FOLDER,
|
||||
ACTION_VIEW_IMAGE
|
||||
ACTION_VIEW_LOCAL_IMAGE,
|
||||
ACTION_VIEW_REMOTE_IMAGE,
|
||||
ACTION_VIEW_LOCAL_PKG,
|
||||
ACTION_VIEW_REMOTE_PKG
|
||||
};
|
||||
|
||||
enum OverWriteType
|
||||
|
||||
@@ -28,6 +28,8 @@ char display_site[32];
|
||||
char language[128];
|
||||
std::vector<std::string> sites;
|
||||
std::vector<std::string> http_servers;
|
||||
std::set<std::string> text_file_extensions;
|
||||
std::set<std::string> image_file_extensions;
|
||||
std::map<std::string, RemoteSettings> site_settings;
|
||||
PackageUrlInfo install_pkg_url;
|
||||
char favorite_urls[MAX_FAVORITE_URLS][512];
|
||||
@@ -142,6 +144,8 @@ namespace CONFIG
|
||||
"Site 11", "Site 12", "Site 13", "Site 14", "Site 15", "Site 16", "Site 17", "Site 18", "Site 19", "Site 20"};
|
||||
|
||||
http_servers = {HTTP_SERVER_APACHE, HTTP_SERVER_MS_IIS, HTTP_SERVER_NGINX, HTTP_SERVER_NPX_SERVE};
|
||||
text_file_extensions = { ".txt", ".ini", ".json", ".xml", ".html", ".xhtml", ".conf" };
|
||||
image_file_extensions = { ".bmp", ".jpg", ".jpeg", ".png", ".webp" };
|
||||
|
||||
OpenIniFile(CONFIG_INI_FILE);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "clients/remote_client.h"
|
||||
|
||||
@@ -14,6 +15,8 @@
|
||||
#define CONFIG_INI_FILE DATA_PATH "/config.ini"
|
||||
#define COOKIE_FILE DATA_PATH "/cookies.txt"
|
||||
#define TMP_EDITOR_FILE DATA_PATH "/tmp_editor.txt"
|
||||
#define TMP_SFO_PATH DATA_PATH "/tmp_pkg.sfo"
|
||||
#define TMP_ICON_PATH DATA_PATH "/tmp_icon.png"
|
||||
|
||||
#define CONFIG_GLOBAL "Global"
|
||||
|
||||
@@ -110,6 +113,8 @@ struct PackageUrlInfo
|
||||
|
||||
extern std::vector<std::string> sites;
|
||||
extern std::vector<std::string> http_servers;
|
||||
extern std::set<std::string> text_file_extensions;
|
||||
extern std::set<std::string> image_file_extensions;
|
||||
extern std::map<std::string, RemoteSettings> site_settings;
|
||||
extern char local_directory[255];
|
||||
extern char remote_directory[255];
|
||||
|
||||
+81
-3
@@ -116,7 +116,7 @@ namespace INSTALLER
|
||||
path = uri.quote(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
|
||||
return host + path;
|
||||
}
|
||||
else
|
||||
@@ -265,7 +265,8 @@ namespace INSTALLER
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
else if (ret > 0) goto err;
|
||||
else if (ret > 0)
|
||||
goto err;
|
||||
|
||||
ret = sceBgftServiceDownloadStartTask(task_id);
|
||||
if (ret)
|
||||
@@ -346,7 +347,8 @@ namespace INSTALLER
|
||||
FS::Rm(filename);
|
||||
}
|
||||
}
|
||||
else if (ret > 0) goto err;
|
||||
else if (ret > 0)
|
||||
goto err;
|
||||
|
||||
ret = sceBgftServiceDownloadStartTask(task_id);
|
||||
if (ret)
|
||||
@@ -380,4 +382,80 @@ namespace INSTALLER
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ExtractLocalPkg(const std::string &filename, pkg_header *pkg_hdr, const std::string sfo_path, const std::string icon_path)
|
||||
{
|
||||
pkg_header tmp_hdr;
|
||||
pkg_header *p_hdr = pkg_hdr;
|
||||
if (p_hdr == nullptr)
|
||||
{
|
||||
FS::Head(filename, &tmp_hdr, sizeof(pkg_header));
|
||||
p_hdr = &tmp_hdr;
|
||||
}
|
||||
|
||||
size_t entry_count = BE32(p_hdr->pkg_entry_count);
|
||||
uint32_t entry_table_offset = BE32(p_hdr->pkg_table_offset);
|
||||
uint64_t entry_table_size = entry_count * sizeof(pkg_table_entry);
|
||||
void *entry_table_data = malloc(entry_table_size);
|
||||
|
||||
FILE *fd = FS::OpenRead(filename);
|
||||
FS::Seek(fd, entry_table_offset);
|
||||
FS::Read(fd, entry_table_data, entry_table_size);
|
||||
|
||||
pkg_table_entry *entries = (pkg_table_entry *)entry_table_data;
|
||||
void* param_sfo_data = NULL;
|
||||
uint32_t param_sfo_offset = 0;
|
||||
uint32_t param_sfo_size = 0;
|
||||
void *icon0_png_data = NULL;
|
||||
uint32_t icon0_png_offset = 0;
|
||||
uint32_t icon0_png_size = 0;
|
||||
short items = 0;
|
||||
for (size_t i = 0; i < entry_count; ++i)
|
||||
{
|
||||
switch (BE32(entries[i].id))
|
||||
{
|
||||
case PKG_ENTRY_ID__PARAM_SFO:
|
||||
param_sfo_offset = BE32(entries[i].offset);
|
||||
param_sfo_size = BE32(entries[i].size);
|
||||
items++;
|
||||
break;
|
||||
case PKG_ENTRY_ID__ICON0_PNG:
|
||||
icon0_png_offset = BE32(entries[i].offset);
|
||||
icon0_png_size = BE32(entries[i].size);
|
||||
items++;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (items == 2)
|
||||
break;
|
||||
}
|
||||
free(entry_table_data);
|
||||
|
||||
if (param_sfo_offset > 0 && param_sfo_size > 0)
|
||||
{
|
||||
param_sfo_data = malloc(param_sfo_size);
|
||||
FILE *out = FS::Create(sfo_path);
|
||||
FS::Seek(fd, param_sfo_offset);
|
||||
FS::Read(fd, param_sfo_data, param_sfo_size);
|
||||
FS::Write(out, param_sfo_data, param_sfo_size);
|
||||
FS::Close(out);
|
||||
free(param_sfo_data);
|
||||
}
|
||||
|
||||
if (icon0_png_offset > 0 && icon0_png_size > 0)
|
||||
{
|
||||
icon0_png_data = malloc(icon0_png_size);
|
||||
FILE *out = FS::Create(icon_path);
|
||||
FS::Seek(fd, icon0_png_offset);
|
||||
FS::Read(fd, icon0_png_data, icon0_png_size);
|
||||
FS::Write(out, icon0_png_data, icon0_png_size);
|
||||
FS::Close(out);
|
||||
free(icon0_png_data);
|
||||
}
|
||||
|
||||
FS::Close(fd);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+40
-30
@@ -1,30 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#define SWAP16(x) \
|
||||
((uint16_t)( \
|
||||
(((uint16_t)(x) & UINT16_C(0x00FF)) << 8) | \
|
||||
(((uint16_t)(x) & UINT16_C(0xFF00)) >> 8) \
|
||||
))
|
||||
#define SWAP16(x) \
|
||||
((uint16_t)((((uint16_t)(x)&UINT16_C(0x00FF)) << 8) | \
|
||||
(((uint16_t)(x)&UINT16_C(0xFF00)) >> 8)))
|
||||
|
||||
#define SWAP32(x) \
|
||||
((uint32_t)( \
|
||||
(((uint32_t)(x) & UINT32_C(0x000000FF)) << 24) | \
|
||||
(((uint32_t)(x) & UINT32_C(0x0000FF00)) << 8) | \
|
||||
(((uint32_t)(x) & UINT32_C(0x00FF0000)) >> 8) | \
|
||||
(((uint32_t)(x) & UINT32_C(0xFF000000)) >> 24) \
|
||||
))
|
||||
#define SWAP32(x) \
|
||||
((uint32_t)((((uint32_t)(x)&UINT32_C(0x000000FF)) << 24) | \
|
||||
(((uint32_t)(x)&UINT32_C(0x0000FF00)) << 8) | \
|
||||
(((uint32_t)(x)&UINT32_C(0x00FF0000)) >> 8) | \
|
||||
(((uint32_t)(x)&UINT32_C(0xFF000000)) >> 24)))
|
||||
|
||||
#define SWAP64(x) \
|
||||
((uint64_t)( \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0x00000000000000FF)) << 56) | \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0x000000000000FF00)) << 40) | \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0x0000000000FF0000)) << 24) | \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0x00000000FF000000)) << 8) | \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0x000000FF00000000)) >> 8) | \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0x0000FF0000000000)) >> 24) | \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0x00FF000000000000)) >> 40) | \
|
||||
(uint64_t)(((uint64_t)(x) & UINT64_C(0xFF00000000000000)) >> 56) \
|
||||
))
|
||||
#define SWAP64(x) \
|
||||
((uint64_t)((uint64_t)(((uint64_t)(x)&UINT64_C(0x00000000000000FF)) << 56) | \
|
||||
(uint64_t)(((uint64_t)(x)&UINT64_C(0x000000000000FF00)) << 40) | \
|
||||
(uint64_t)(((uint64_t)(x)&UINT64_C(0x0000000000FF0000)) << 24) | \
|
||||
(uint64_t)(((uint64_t)(x)&UINT64_C(0x00000000FF000000)) << 8) | \
|
||||
(uint64_t)(((uint64_t)(x)&UINT64_C(0x000000FF00000000)) >> 8) | \
|
||||
(uint64_t)(((uint64_t)(x)&UINT64_C(0x0000FF0000000000)) >> 24) | \
|
||||
(uint64_t)(((uint64_t)(x)&UINT64_C(0x00FF000000000000)) >> 40) | \
|
||||
(uint64_t)(((uint64_t)(x)&UINT64_C(0xFF00000000000000)) >> 56)))
|
||||
|
||||
#define LE16(x) (x)
|
||||
#define LE32(x) (x)
|
||||
@@ -47,6 +41,9 @@
|
||||
#define PKG_CONTENT_FLAGS_DELTA_PATCH 0x41000000
|
||||
#define PKG_CONTENT_FLAGS_CUMULATIVE_PATCH 0x60000000
|
||||
|
||||
#define PKG_ENTRY_ID__PARAM_SFO 0x1000
|
||||
#define PKG_ENTRY_ID__ICON0_PNG 0x1200
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t pkg_magic; // 0x000 - 0x7F434E54
|
||||
@@ -98,11 +95,23 @@ typedef struct
|
||||
unsigned char pkg_digest[0x20]; // 0xFE0
|
||||
} pkg_header;
|
||||
|
||||
enum pkg_content_type {
|
||||
PKG_CONTENT_TYPE_GD = 0x1A, /* pkg_ps4_app, pkg_ps4_patch, pkg_ps4_remaster */
|
||||
PKG_CONTENT_TYPE_AC = 0x1B, /* pkg_ps4_ac_data, pkg_ps4_sf_theme, pkg_ps4_theme */
|
||||
PKG_CONTENT_TYPE_AL = 0x1C, /* pkg_ps4_ac_nodata */
|
||||
PKG_CONTENT_TYPE_DP = 0x1E, /* pkg_ps4_delta_patch */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t id; // File ID, useful for files without a filename entry
|
||||
uint32_t filename_offset; // Offset into the filenames table (ID 0x200) where this file's name is located
|
||||
uint32_t flags1; // Flags including encrypted flag, etc
|
||||
uint32_t flags2; // Flags including encryption key index, etc
|
||||
uint32_t offset; // Offset into PKG to find the file
|
||||
uint32_t size; // Size of the file
|
||||
uint64_t padding; // blank padding
|
||||
} pkg_table_entry;
|
||||
|
||||
enum pkg_content_type
|
||||
{
|
||||
PKG_CONTENT_TYPE_GD = 0x1A, /* pkg_ps4_app, pkg_ps4_patch, pkg_ps4_remaster */
|
||||
PKG_CONTENT_TYPE_AC = 0x1B, /* pkg_ps4_ac_data, pkg_ps4_sf_theme, pkg_ps4_theme */
|
||||
PKG_CONTENT_TYPE_AL = 0x1C, /* pkg_ps4_ac_nodata */
|
||||
PKG_CONTENT_TYPE_DP = 0x1E, /* pkg_ps4_delta_patch */
|
||||
};
|
||||
|
||||
namespace INSTALLER
|
||||
@@ -111,7 +120,8 @@ namespace INSTALLER
|
||||
void Exit(void);
|
||||
|
||||
bool canInstallRemotePkg(const std::string &url);
|
||||
std::string getRemoteUrl(const std::string filename, bool encodeUrl=false);
|
||||
std::string getRemoteUrl(const std::string filename, bool encodeUrl = false);
|
||||
int InstallRemotePkg(const std::string &filename, pkg_header *header);
|
||||
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install=false);
|
||||
int InstallLocalPkg(const std::string &filename, pkg_header *header, bool remove_after_install = false);
|
||||
bool ExtractLocalPkg(const std::string &filename, pkg_header *pkg_header, const std::string sfo_path, const std::string icon_path);
|
||||
}
|
||||
+1
-2
@@ -11,7 +11,7 @@
|
||||
#include <orbis/Pad.h>
|
||||
#include <orbis/AudioOut.h>
|
||||
#include <orbis/Net.h>
|
||||
#include <dbglogger.h>
|
||||
// #include <dbglogger.h>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "SDL2/SDL.h"
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "installer.h"
|
||||
#include "system.h"
|
||||
#include "textures.h"
|
||||
// #include "dbglogger.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <cstring>
|
||||
#include "sfo.h"
|
||||
|
||||
static constexpr uint32_t SFO_MAGIC = 0x46535000;
|
||||
|
||||
namespace SFO {
|
||||
const char* GetString(const char* buffer, size_t size, const char *name)
|
||||
{
|
||||
if (size < sizeof(SfoHeader))
|
||||
return nullptr;
|
||||
|
||||
const SfoHeader* header = reinterpret_cast<const SfoHeader*>(buffer);
|
||||
const SfoEntry* entries =
|
||||
reinterpret_cast<const SfoEntry*>(buffer + sizeof(SfoHeader));
|
||||
|
||||
if (header->magic != SFO_MAGIC)
|
||||
return nullptr;
|
||||
|
||||
if (size < sizeof(SfoHeader) + header->count * sizeof(SfoEntry))
|
||||
return nullptr;
|
||||
|
||||
for (uint32_t i = 0; i < header->count; i++) {
|
||||
const char* key = reinterpret_cast<const char*>(buffer + header->keyofs + entries[i].nameofs);
|
||||
if (strcmp(key, name) == 0)
|
||||
return reinterpret_cast<const char*>(buffer + header->valofs + entries[i].dataofs);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef LAUNCHER_SFO_H
|
||||
#define LAUNCHER_SFO_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
struct SfoHeader
|
||||
{
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint32_t keyofs;
|
||||
uint32_t valofs;
|
||||
uint32_t count;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct SfoEntry
|
||||
{
|
||||
uint16_t nameofs;
|
||||
uint8_t alignment;
|
||||
uint8_t type;
|
||||
uint32_t valsize;
|
||||
uint32_t totalsize;
|
||||
uint32_t dataofs;
|
||||
} __attribute__((packed));
|
||||
|
||||
namespace SFO {
|
||||
const char* GetString(const char* buffer, size_t size, const char *name);
|
||||
}
|
||||
|
||||
#endif
|
||||
+11
-4
@@ -10,16 +10,23 @@ namespace Textures {
|
||||
SDL_Surface *image = IMG_Load(filename.c_str());
|
||||
if (image == nullptr)
|
||||
return false;
|
||||
image = SDL_ConvertSurfaceFormat(image, SDL_PIXELFORMAT_RGBA8888, 0);
|
||||
SDL_Texture *sdl_texture = SDL_CreateTextureFromSurface(renderer, image);
|
||||
SDL_Surface *formated_image = SDL_ConvertSurfaceFormat(image, SDL_PIXELFORMAT_RGBA8888, 0);
|
||||
if (formated_image == nullptr)
|
||||
{
|
||||
SDL_FreeSurface(image);
|
||||
}
|
||||
SDL_Texture *sdl_texture = SDL_CreateTextureFromSurface(renderer, formated_image);
|
||||
if (sdl_texture == nullptr)
|
||||
{
|
||||
SDL_FreeSurface(formated_image);
|
||||
SDL_FreeSurface(image);
|
||||
return false;
|
||||
}
|
||||
texture->id = sdl_texture;
|
||||
texture->height = image->h;
|
||||
texture->width = image->w;
|
||||
texture->height = formated_image->h;
|
||||
texture->width = formated_image->w;
|
||||
|
||||
SDL_FreeSurface(formated_image);
|
||||
SDL_FreeSurface(image);
|
||||
|
||||
return true;
|
||||
|
||||
+29
-5
@@ -587,10 +587,13 @@ namespace Windows
|
||||
if (dot_pos != std::string::npos)
|
||||
{
|
||||
std::string ext = filename.substr(dot_pos);
|
||||
if (ext.compare(".bmp") == 0 || ext.compare(".jpg") == 0 || ext.compare(".png") == 0 ||
|
||||
ext.compare(".jpeg") == 0 || ext.compare(".webp") == 0)
|
||||
if (image_file_extensions.find(ext) != image_file_extensions.end())
|
||||
{
|
||||
selected_action = ACTION_VIEW_IMAGE;
|
||||
selected_action = ACTION_VIEW_LOCAL_IMAGE;
|
||||
}
|
||||
else if (ext.compare(".pkg") == 0)
|
||||
{
|
||||
INSTALLER::ExtractLocalPkg(selected_local_file.path, nullptr, TMP_SFO_PATH, TMP_ICON_PATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -734,11 +737,24 @@ namespace Windows
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::Selectable(item.name, false, ImGuiSelectableFlags_SpanAllColumns, ImVec2(919, 0)))
|
||||
{
|
||||
selected_remote_file = item;
|
||||
if (item.isDir)
|
||||
{
|
||||
selected_remote_file = item;
|
||||
selected_action = ACTION_CHANGE_REMOTE_DIRECTORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string filename = Util::ToLower(selected_remote_file.name);
|
||||
size_t dot_pos = filename.find_last_of(".");
|
||||
if (dot_pos != std::string::npos)
|
||||
{
|
||||
std::string ext = filename.substr(dot_pos);
|
||||
if (image_file_extensions.find(ext) != image_file_extensions.end())
|
||||
{
|
||||
selected_action = ACTION_VIEW_REMOTE_IMAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::IsItemFocused())
|
||||
{
|
||||
@@ -2022,13 +2038,21 @@ namespace Windows
|
||||
sprintf(status_message, "\"%s\" %s", remote_directory, lang_strings[STR_SET_DEFAULT_DIRECTORY_MSG]);
|
||||
selected_action = ACTION_NONE;
|
||||
break;
|
||||
case ACTION_VIEW_IMAGE:
|
||||
case ACTION_VIEW_LOCAL_IMAGE:
|
||||
if (Textures::LoadImageFile(selected_local_file.path, &texture))
|
||||
{
|
||||
view_image = true;
|
||||
}
|
||||
selected_action = ACTION_NONE;
|
||||
break;
|
||||
case ACTION_VIEW_REMOTE_IMAGE:
|
||||
remoteclient->Get(TMP_ICON_PATH, selected_remote_file.path);
|
||||
if (Textures::LoadImageFile(TMP_ICON_PATH, &texture))
|
||||
{
|
||||
view_image = true;
|
||||
}
|
||||
selected_action = ACTION_NONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user