mirror of
https://github.com/mmozeiko/pkg2zip.git
synced 2026-09-03 03:29:59 +03:00
proper folder structure for PSX pkg files
This commit is contained in:
@@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
[![Travis CI Build Status][img_travis]][travis] [![AppVeyor Build Status][img_appveyor]][appveyor] [![Downloads][img_downloads]][downloads] [![Release][img_latest]][latest] [![License][img_license]][license]
|
[![Travis CI Build Status][img_travis]][travis] [![AppVeyor Build Status][img_appveyor]][appveyor] [![Downloads][img_downloads]][downloads] [![Release][img_latest]][latest] [![License][img_license]][license]
|
||||||
|
|
||||||
Utility that decrypts PlayStation Vita pkg file and creates zip package.
|
Utility that decrypts PlayStation Vita pkg file and creates zip package. Supports also PSX pkg files for use with [Adrenaline](https://github.com/TheOfficialFloW/Adrenaline).
|
||||||
|
|
||||||
Optionally saves [NoNpDrm](https://github.com/TheOfficialFloW/NoNpDrm) license into work.bin file. You must provide license key.
|
Optionally saves [NoNpDrm](https://github.com/TheOfficialFloW/NoNpDrm) license into work.bin file. You must provide license key.
|
||||||
|
|
||||||
DLC support available when VitaShell will include [this pull request](https://github.com/TheOfficialFloW/VitaShell/pull/310).
|
# Requirements
|
||||||
|
|
||||||
|
* [Henkaku](https://henkaku.xyz/) / [Enso](https://enso.henkaku.xyz/)
|
||||||
|
* [NoNpDrm](https://github.com/TheOfficialFloW/NoNpDrm)
|
||||||
|
* to use DLC pkg files, [VitaShell](https://github.com/TheOfficialFloW/VitaShell) **v1.76** or newer required
|
||||||
|
* [Adrenaline](https://github.com/TheOfficialFloW/Adrenaline) for PSX titles
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
@@ -14,11 +19,12 @@ DLC support available when VitaShell will include [this pull request](https://gi
|
|||||||
* **small**, has no external library dependencies and uses very minimal dynamic memory allocations.
|
* **small**, has no external library dependencies and uses very minimal dynamic memory allocations.
|
||||||
* **fast**, uses AESNI hardware accelerated AES decryption if supported by CPU (requires [AESNI](https://en.wikipedia.org/wiki/AES_instruction_set) and [SSSE3](https://en.wikipedia.org/wiki/SSSE3) instructions).
|
* **fast**, uses AESNI hardware accelerated AES decryption if supported by CPU (requires [AESNI](https://en.wikipedia.org/wiki/AES_instruction_set) and [SSSE3](https://en.wikipedia.org/wiki/SSSE3) instructions).
|
||||||
* **simple**, creates zip package with same folder structure that Vita expects (just drag & drop all file from zip archive to ux0:). Zip file is created directly from pkg without any intermediate temporary files.
|
* **simple**, creates zip package with same folder structure that Vita expects (just drag & drop all file from zip archive to ux0:). Zip file is created directly from pkg without any intermediate temporary files.
|
||||||
* **DLC** and **PATCH** pkg support.
|
* **DLC** and **PATCH** pkg unpacking.
|
||||||
|
* **PSX** pkg unpacking.
|
||||||
|
|
||||||
Limitations:
|
Limitations:
|
||||||
|
|
||||||
* currently no PSM pkg files are supported.
|
* currently no PSM, PSP or PSP Mini pkg files are supported.
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
@@ -34,6 +40,8 @@ If you don't have zRIF fake license, but just want to unpack files, then omit la
|
|||||||
|
|
||||||
Resulting zip file will not include work.bin. This is useful for patch pkg files.
|
Resulting zip file will not include work.bin. This is useful for patch pkg files.
|
||||||
|
|
||||||
|
PSX pkg files do not require zRIF argument. It will be ignored.
|
||||||
|
|
||||||
# Generating zRIF string
|
# Generating zRIF string
|
||||||
|
|
||||||
If you have working main.bin file you can create zRIF string with `rif2zrif.py` python script:
|
If you have working main.bin file you can create zRIF string with `rif2zrif.py` python script:
|
||||||
|
|||||||
@@ -333,7 +333,8 @@ int main(int argc, char* argv[])
|
|||||||
meta_offset += 2 * sizeof(uint32_t) + size;
|
meta_offset += 2 * sizeof(uint32_t) + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int psp = content_type == 6 || content_type == 7 || content_type == 0xf; // PSX, PSP, PSPMini
|
int psx = content_type == 6;
|
||||||
|
int psp = content_type == 7 || content_type == 0xf; // PSX, PSP, PSPMini
|
||||||
int dlc = content_type == 0x16; // APP
|
int dlc = content_type == 0x16; // APP
|
||||||
|
|
||||||
aes128_key ps3_key;
|
aes128_key ps3_key;
|
||||||
@@ -376,7 +377,7 @@ int main(int argc, char* argv[])
|
|||||||
// https://github.com/TheOfficialFloW/NoNpDrm/blob/v1.1/src/main.c#L42
|
// https://github.com/TheOfficialFloW/NoNpDrm/blob/v1.1/src/main.c#L42
|
||||||
uint8_t rif[512];
|
uint8_t rif[512];
|
||||||
|
|
||||||
if (psp)
|
if (psp || psx)
|
||||||
{
|
{
|
||||||
find_psp_sfo(&key, &ps3_key, iv, pkg, pkg_size, enc_offset, items_offset, item_count, title);
|
find_psp_sfo(&key, &ps3_key, iv, pkg, pkg_size, enc_offset, items_offset, item_count, title);
|
||||||
}
|
}
|
||||||
@@ -397,10 +398,17 @@ int main(int argc, char* argv[])
|
|||||||
char path[1024];
|
char path[1024];
|
||||||
if (psp)
|
if (psp)
|
||||||
{
|
{
|
||||||
const char* type_str = content_type == 6 ? "PSX" : content_type == 7 ? "PSP" : "PSPMini";
|
id = (char*)pkg_header + 0x37;
|
||||||
snprintf(path, sizeof(path), "%s [%.9s] [%s].zip", title, pkg_header + 0x37, type_str);
|
const char* type_str = content_type == 7 ? "PSP" : "PSPMini";
|
||||||
|
snprintf(path, sizeof(path), "%s [%.9s] [%s].zip", title, id, type_str);
|
||||||
printf("[*] unpacking %s\n", type_str);
|
printf("[*] unpacking %s\n", type_str);
|
||||||
}
|
}
|
||||||
|
else if (psx)
|
||||||
|
{
|
||||||
|
id = (char*)pkg_header + 0x37;
|
||||||
|
snprintf(path, sizeof(path), "%s [%.9s] [PSX].zip", title, id);
|
||||||
|
printf("[*] unpacking PSX\n");
|
||||||
|
}
|
||||||
else if (dlc)
|
else if (dlc)
|
||||||
{
|
{
|
||||||
snprintf(path, sizeof(path), "%s [%.9s] [%s] [DLC-%s].zip", title, id, get_region(id), id2);
|
snprintf(path, sizeof(path), "%s [%.9s] [%s] [DLC-%s].zip", title, id, get_region(id), id2);
|
||||||
@@ -422,8 +430,27 @@ int main(int argc, char* argv[])
|
|||||||
zip z;
|
zip z;
|
||||||
zip_create(&z, path);
|
zip_create(&z, path);
|
||||||
|
|
||||||
|
char root[64];
|
||||||
|
|
||||||
if (psp)
|
if (psp)
|
||||||
{
|
{
|
||||||
|
root[0] = 0;
|
||||||
|
}
|
||||||
|
else if (psx)
|
||||||
|
{
|
||||||
|
snprintf(path, sizeof(path), "pspemu/");
|
||||||
|
zip_add_folder(&z, path);
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "pspemu/PSP/");
|
||||||
|
zip_add_folder(&z, path);
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "pspemu/PSP/GAME/");
|
||||||
|
zip_add_folder(&z, path);
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "pspemu/PSP/GAME/%.9s/", id);
|
||||||
|
zip_add_folder(&z, path);
|
||||||
|
|
||||||
|
snprintf(root, sizeof(root), "pspemu/PSP/GAME/%.9s", id);
|
||||||
}
|
}
|
||||||
else if (dlc)
|
else if (dlc)
|
||||||
{
|
{
|
||||||
@@ -435,6 +462,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
snprintf(path, sizeof(path), "addcont/%.9s/%s/", id, id2);
|
snprintf(path, sizeof(path), "addcont/%.9s/%s/", id, id2);
|
||||||
zip_add_folder(&z, path);
|
zip_add_folder(&z, path);
|
||||||
|
|
||||||
|
snprintf(root, sizeof(root), "addcont/%.9s/%s", id, id2);
|
||||||
}
|
}
|
||||||
else if (patch)
|
else if (patch)
|
||||||
{
|
{
|
||||||
@@ -443,6 +472,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
snprintf(path, sizeof(path), "patch/%.9s/", id);
|
snprintf(path, sizeof(path), "patch/%.9s/", id);
|
||||||
zip_add_folder(&z, path);
|
zip_add_folder(&z, path);
|
||||||
|
|
||||||
|
snprintf(root, sizeof(root), "patch/%.9s", id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -451,24 +482,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
snprintf(path, sizeof(path), "app/%.9s/", id);
|
snprintf(path, sizeof(path), "app/%.9s/", id);
|
||||||
zip_add_folder(&z, path);
|
zip_add_folder(&z, path);
|
||||||
}
|
|
||||||
|
|
||||||
char root[64];
|
snprintf(root, sizeof(root), "app/%.9s/", id);
|
||||||
if (psp)
|
|
||||||
{
|
|
||||||
root[0] = 0;
|
|
||||||
}
|
|
||||||
else if (dlc)
|
|
||||||
{
|
|
||||||
snprintf(root, sizeof(root), "addcont/%.9s/%s", id, id2);
|
|
||||||
}
|
|
||||||
else if (patch)
|
|
||||||
{
|
|
||||||
snprintf(root, sizeof(root), "patch/%.9s", id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(root, sizeof(root), "app/%.9s", id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[*] decrypting...\n");
|
printf("[*] decrypting...\n");
|
||||||
@@ -501,7 +516,15 @@ int main(int argc, char* argv[])
|
|||||||
fatal("ERROR: pkg file contains file with very long name\n");
|
fatal("ERROR: pkg file contains file with very long name\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const aes128_key* item_key = psp && psp_type == 0x90 ? &key : &ps3_key;
|
const aes128_key* item_key;
|
||||||
|
if (psp || psx)
|
||||||
|
{
|
||||||
|
item_key = psp_type == 0x90 ? &key : &ps3_key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item_key = &key;
|
||||||
|
}
|
||||||
|
|
||||||
char name[ZIP_MAX_FILENAME];
|
char name[ZIP_MAX_FILENAME];
|
||||||
sys_read(pkg, enc_offset + name_offset, name, name_size);
|
sys_read(pkg, enc_offset + name_offset, name, name_size);
|
||||||
@@ -512,20 +535,40 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (flags == 4 || flags == 18)
|
if (flags == 4 || flags == 18)
|
||||||
{
|
{
|
||||||
snprintf(path, sizeof(path), "%s/%s/", root, name);
|
if (!psx)
|
||||||
|
{
|
||||||
zip_add_folder(&z, path);
|
snprintf(path, sizeof(path), "%s/%s/", root, name);
|
||||||
|
zip_add_folder(&z, path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int decrypt = 1;
|
int decrypt = 1;
|
||||||
if (!psp && strcmp("sce_sys/package/digs.bin", name) == 0)
|
if (!psp && !psx && strcmp("sce_sys/package/digs.bin", name) == 0)
|
||||||
{
|
{
|
||||||
snprintf(name, sizeof(name), "%s", "sce_sys/package/body.bin");
|
snprintf(name, sizeof(name), "%s", "sce_sys/package/body.bin");
|
||||||
decrypt = 0;
|
decrypt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", root, name);
|
if (psx)
|
||||||
|
{
|
||||||
|
if (strcmp("USRDIR/CONTENT/DOCUMENT.DAT", name) == 0)
|
||||||
|
{
|
||||||
|
snprintf(path, sizeof(path), "%s/DOCUMENT.DAT", root);
|
||||||
|
}
|
||||||
|
else if (strcmp("USRDIR/CONTENT/EBOOT.PBP", name) == 0)
|
||||||
|
{
|
||||||
|
snprintf(path, sizeof(path), "%s/EBOOT.PBP", root);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(path, sizeof(path), "%s/%s", root, name);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t offset = data_offset;
|
uint64_t offset = data_offset;
|
||||||
|
|
||||||
@@ -550,7 +593,7 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!psp)
|
if (!psp && !psx)
|
||||||
{
|
{
|
||||||
printf("[*] creating head.bin\n");
|
printf("[*] creating head.bin\n");
|
||||||
snprintf(path, sizeof(path), "%s/sce_sys/package/head.bin", root);
|
snprintf(path, sizeof(path), "%s/sce_sys/package/head.bin", root);
|
||||||
@@ -570,7 +613,7 @@ int main(int argc, char* argv[])
|
|||||||
zip_end_file(&z);
|
zip_end_file(&z);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!psp)
|
if (!psp && !psx)
|
||||||
{
|
{
|
||||||
printf("[*] creating tail.bin\n");
|
printf("[*] creating tail.bin\n");
|
||||||
snprintf(path, sizeof(path), "%s/sce_sys/package/tail.bin", root);
|
snprintf(path, sizeof(path), "%s/sce_sys/package/tail.bin", root);
|
||||||
@@ -588,7 +631,7 @@ int main(int argc, char* argv[])
|
|||||||
zip_end_file(&z);
|
zip_end_file(&z);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!psp)
|
if (!psp && !psx)
|
||||||
{
|
{
|
||||||
printf("[*] creating stat.bin\n");
|
printf("[*] creating stat.bin\n");
|
||||||
snprintf(path, sizeof(path), "%s/sce_sys/package/stat.bin", root);
|
snprintf(path, sizeof(path), "%s/sce_sys/package/stat.bin", root);
|
||||||
@@ -599,7 +642,7 @@ int main(int argc, char* argv[])
|
|||||||
zip_end_file(&z);
|
zip_end_file(&z);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!psp && !patch && argc == 3)
|
if (!psp && !psx && !patch && argc == 3)
|
||||||
{
|
{
|
||||||
printf("[*] creating work.bin\n");
|
printf("[*] creating work.bin\n");
|
||||||
snprintf(path, sizeof(path), "%s/sce_sys/package/work.bin", root);
|
snprintf(path, sizeof(path), "%s/sce_sys/package/work.bin", root);
|
||||||
@@ -611,7 +654,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
zip_close(&z);
|
zip_close(&z);
|
||||||
|
|
||||||
if (!psp && !dlc)
|
if (!psp && !psx && !dlc)
|
||||||
{
|
{
|
||||||
printf("[*] minimum fw version required: %s\n", min_version);
|
printf("[*] minimum fw version required: %s\n", min_version);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user