proper folder structure for PSX pkg files

This commit is contained in:
Martins Mozeiko
2017-10-30 22:03:31 -07:00
parent 36bdf4c529
commit cb2a4e0c3f
2 changed files with 87 additions and 36 deletions
+12 -4
View File
@@ -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:
+75 -32
View File
@@ -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);
} }