add -x argument to create individual files without zip file

This commit is contained in:
Martins Mozeiko
2017-10-30 23:25:56 -07:00
parent cb2a4e0c3f
commit 68e7dc8051
6 changed files with 265 additions and 93 deletions
+4
View File
@@ -40,6 +40,10 @@ 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.
To avoid zipping process and create individual files, use `-x` argument (must come before pkg file):
pkg2zip -x package.pkg [zRIF_STRING]
PSX pkg files do not require zRIF argument. It will be ignored.
# Generating zRIF string
+1 -1
View File
@@ -3,7 +3,7 @@
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=amd64 -host_arch=amd64
cd "%~dp0"
set CL=/nologo /errorReport:none /Gm- /GF /GS- /MT /W4 /WX /wd4324
set CL=/nologo /errorReport:none /Gm- /GF /GS- /MT /W4 /WX /wd4324 /D_CRT_SECURE_NO_DEPRECATE
set LINK=/errorReport:none /INCREMENTAL:NO
set CL=%CL% /Ox
+197 -88
View File
@@ -261,18 +261,119 @@ static const char* get_region(const char* id)
}
}
static zip out_zip;
static int out_zipped;
static sys_file out_file;
static uint64_t out_file_offset;
static void out_begin(const char* name, int zipped)
{
if (zipped)
{
zip_create(&out_zip, name);
}
else
{
sys_mkdir(name);
}
out_zipped = zipped;
}
static void out_end(void)
{
if (out_zipped)
{
zip_close(&out_zip);
}
}
static void out_add_folder(const char* path)
{
if (out_zipped)
{
zip_add_folder(&out_zip, path);
}
else
{
sys_mkdir(path);
}
}
static void out_begin_file(const char* name)
{
if (out_zipped)
{
zip_begin_file(&out_zip, name);
}
else
{
out_file = sys_create(name);
out_file_offset = 0;
}
}
static void out_end_file(void)
{
if (out_zipped)
{
zip_end_file(&out_zip);
}
else
{
sys_close(out_file);
}
}
static void out_write(const void* buffer, uint32_t size)
{
if (out_zipped)
{
zip_write_file(&out_zip, buffer, size);
}
else
{
sys_write(out_file, out_file_offset, buffer, size);
out_file_offset += size;
}
}
int main(int argc, char* argv[])
{
printf("pkg2zip v1.5\n");
if (argc < 2 || argc > 3)
int zipped = 1;
const char* pkg_arg = NULL;
const char* zrif_arg = NULL;
for (int i = 1; i < argc; i++)
{
fatal("Usage: %s file.pkg [zRIF]\n", argv[0]);
if (strcmp(argv[i], "-x") == 0)
{
zipped = 0;
}
else
{
if (pkg_arg != NULL)
{
zrif_arg = argv[i];
break;
}
else
{
pkg_arg = argv[i];
}
}
}
if (pkg_arg == NULL)
{
fprintf(stderr, "ERROR: no pkg file specified\n");
fatal("Usage: %s [-x] file.pkg [zRIF]\n", argv[0]);
}
printf("[*] loading...\n");
uint64_t pkg_size;
sys_file pkg = sys_open(argv[1], &pkg_size);
sys_file pkg = sys_open(pkg_arg, &pkg_size);
uint8_t pkg_header[PKG_HEADER_SIZE + PKG_HEADER_EXT_SIZE];
sys_read(pkg, 0, pkg_header, sizeof(pkg_header));
@@ -385,9 +486,9 @@ int main(int argc, char* argv[])
{
parse_sfo(pkg, sfo_offset, sfo_size, &patch, title, content, min_version, pkg_version);
if (argc == 3 && !patch)
if (!patch && zrif_arg != NULL)
{
zrif_decode(argv[2], rif);
zrif_decode(zrif_arg, rif);
if (strncmp((char*)rif + 0x10, content, 0x30) != 0)
{
fatal("ERROR: zRIF content id '%s' doesn't match pkg '%s'\n", rif + 0x10, content);
@@ -395,98 +496,106 @@ int main(int argc, char* argv[])
}
}
char path[1024];
const char* ext = zipped ? ".zip" : "";
char root[1024];
if (psp)
{
id = (char*)pkg_header + 0x37;
const char* type_str = content_type == 7 ? "PSP" : "PSPMini";
snprintf(path, sizeof(path), "%s [%.9s] [%s].zip", title, id, type_str);
snprintf(root, sizeof(root), "%s [%.9s] [%s]%s", title, id, type_str, ext);
printf("[*] unpacking %s\n", type_str);
}
else if (psx)
{
id = (char*)pkg_header + 0x37;
snprintf(path, sizeof(path), "%s [%.9s] [PSX].zip", title, id);
snprintf(root, sizeof(root), "%s [%.9s] [PSX]%s", title, id, ext);
printf("[*] unpacking PSX\n");
}
else if (dlc)
{
snprintf(path, sizeof(path), "%s [%.9s] [%s] [DLC-%s].zip", title, id, get_region(id), id2);
snprintf(root, sizeof(root), "%s [%.9s] [%s] [DLC-%s]%s", title, id, get_region(id), id2, ext);
printf("[*] unpacking DLC\n");
}
else if (patch)
{
snprintf(path, sizeof(path), "%s [%.9s] [%s] [PATCH] [v%s].zip", title, id, get_region(id), pkg_version);
snprintf(root, sizeof(root), "%s [%.9s] [%s] [PATCH] [v%s]%s", title, id, get_region(id), pkg_version, ext);
printf("[*] unpacking PATCH\n");
}
else
{
snprintf(path, sizeof(path), "%s [%.9s] [%s].zip", title, id, get_region(id));
snprintf(root, sizeof(root), "%s [%.9s] [%s]%s", title, id, get_region(id), ext);
printf("[*] unpacking APP\n");
}
printf("[*] creating '%s' archive\n", path);
out_begin(root, zipped);
zip z;
zip_create(&z, path);
char root[64];
if (psp)
if (zipped)
{
printf("[*] creating '%s' archive\n", root);
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)
{
snprintf(path, sizeof(path), "addcont/");
zip_add_folder(&z, path);
snprintf(path, sizeof(path), "addcont/%.9s/", id);
zip_add_folder(&z, path);
snprintf(path, sizeof(path), "addcont/%.9s/%s/", id, id2);
zip_add_folder(&z, path);
snprintf(root, sizeof(root), "addcont/%.9s/%s", id, id2);
}
else if (patch)
{
snprintf(path, sizeof(path), "patch/");
zip_add_folder(&z, path);
snprintf(path, sizeof(path), "patch/%.9s/", id);
zip_add_folder(&z, path);
snprintf(root, sizeof(root), "patch/%.9s", id);
}
else
{
snprintf(path, sizeof(path), "app/");
zip_add_folder(&z, path);
printf("[*] output to '%s' folder\n", root);
sys_vstrncat(root, sizeof(root), "/");
}
snprintf(path, sizeof(path), "app/%.9s/", id);
zip_add_folder(&z, path);
if (psp)
{
}
else if (psx)
{
sys_vstrncat(root, sizeof(root), "pspemu");
out_add_folder(root);
snprintf(root, sizeof(root), "app/%.9s/", id);
sys_vstrncat(root, sizeof(root), "/PSP");
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/GAME");
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/%.9s", id);
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/");
}
else if (dlc)
{
sys_vstrncat(root, sizeof(root), "addcont");
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/%.9s", id);
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/%s", id2);
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/");
}
else if (patch)
{
sys_vstrncat(root, sizeof(root), "patch");
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/%.9s", id);
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/");
}
else
{
sys_vstrncat(root, sizeof(root), "app");
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/%.9s", id);
out_add_folder(root);
sys_vstrncat(root, sizeof(root), "/");
}
printf("[*] decrypting...\n");
char path[1024];
for (uint32_t item_index = 0; item_index < item_count; item_index++)
{
@@ -537,8 +646,8 @@ int main(int argc, char* argv[])
{
if (!psx)
{
snprintf(path, sizeof(path), "%s/%s/", root, name);
zip_add_folder(&z, path);
snprintf(path, sizeof(path), "%s%s/", root, name);
out_add_folder(path);
}
}
else
@@ -554,11 +663,11 @@ int main(int argc, char* argv[])
{
if (strcmp("USRDIR/CONTENT/DOCUMENT.DAT", name) == 0)
{
snprintf(path, sizeof(path), "%s/DOCUMENT.DAT", root);
snprintf(path, sizeof(path), "%sDOCUMENT.DAT", root);
}
else if (strcmp("USRDIR/CONTENT/EBOOT.PBP", name) == 0)
{
snprintf(path, sizeof(path), "%s/EBOOT.PBP", root);
snprintf(path, sizeof(path), "%sEBOOT.PBP", root);
}
else
{
@@ -567,12 +676,12 @@ int main(int argc, char* argv[])
}
else
{
snprintf(path, sizeof(path), "%s/%s", root, name);
snprintf(path, sizeof(path), "%s%s", root, name);
}
uint64_t offset = data_offset;
zip_begin_file(&z, path);
out_begin_file(path);
while (data_size != 0)
{
uint8_t buffer[1 << 16];
@@ -584,21 +693,21 @@ int main(int argc, char* argv[])
aes128_ctr_xor(item_key, iv, offset / 16, buffer, size);
}
zip_write_file(&z, buffer, size);
out_write(buffer, size);
offset += size;
data_size -= size;
}
zip_end_file(&z);
out_end_file();
}
}
if (!psp && !psx)
{
printf("[*] creating head.bin\n");
snprintf(path, sizeof(path), "%s/sce_sys/package/head.bin", root);
snprintf(path, sizeof(path), "%ssce_sys/package/head.bin", root);
zip_begin_file(&z, path);
out_begin_file(path);
uint64_t head_size = enc_offset + items_size;
uint64_t head_offset = 0;
while (head_size != 0)
@@ -606,53 +715,53 @@ int main(int argc, char* argv[])
uint8_t buffer[1 << 16];
uint32_t size = (uint32_t)min64(head_size, sizeof(buffer));
sys_read(pkg, head_offset, buffer, size);
zip_write_file(&z, buffer, size);
out_write(buffer, size);
head_size -= size;
head_offset += size;
}
zip_end_file(&z);
out_end_file();
}
if (!psp && !psx)
{
printf("[*] creating tail.bin\n");
snprintf(path, sizeof(path), "%s/sce_sys/package/tail.bin", root);
snprintf(path, sizeof(path), "%ssce_sys/package/tail.bin", root);
zip_begin_file(&z, path);
out_begin_file(path);
uint64_t tail_offset = enc_offset + enc_size;
while (tail_offset != pkg_size)
{
uint8_t buffer[1 << 16];
uint32_t size = (uint32_t)min64(pkg_size - tail_offset, sizeof(buffer));
sys_read(pkg, tail_offset, buffer, size);
zip_write_file(&z, buffer, size);
out_write(buffer, size);
tail_offset += size;
}
zip_end_file(&z);
out_end_file();
}
if (!psp && !psx)
{
printf("[*] creating stat.bin\n");
snprintf(path, sizeof(path), "%s/sce_sys/package/stat.bin", root);
snprintf(path, sizeof(path), "%ssce_sys/package/stat.bin", root);
uint8_t stat[768] = { 0 };
zip_begin_file(&z, path);
zip_write_file(&z, stat, sizeof(stat));
zip_end_file(&z);
out_begin_file(path);
out_write(stat, sizeof(stat));
out_end_file();
}
if (!psp && !psx && !patch && argc == 3)
if (!psp && !psx && !patch && zrif_arg != NULL)
{
printf("[*] creating work.bin\n");
snprintf(path, sizeof(path), "%s/sce_sys/package/work.bin", root);
snprintf(path, sizeof(path), "%ssce_sys/package/work.bin", root);
zip_begin_file(&z, path);
zip_write_file(&z, rif, sizeof(rif));
zip_end_file(&z);
out_begin_file(path);
out_write(rif, sizeof(rif));
out_end_file();
}
zip_close(&z);
out_end();
if (!psp && !psx && !dlc)
{
+53
View File
@@ -2,12 +2,29 @@
#include "pkg2zip_utils.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static void sys_mkdir_real(const char* path)
{
WCHAR wpath[MAX_PATH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, MAX_PATH);
if (CreateDirectoryW(wpath, NULL) == 0)
{
if (GetLastError() != ERROR_ALREADY_EXISTS)
{
fatal("ERROR: cannot create '%s' folder\n", path);
}
}
}
sys_file sys_open(const char* fname, uint64_t* size)
{
WCHAR path[MAX_PATH];
@@ -82,9 +99,21 @@ void sys_write(sys_file file, uint64_t offset, const void* buffer, uint32_t size
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
static void sys_mkdir_real(const char* path)
{
if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
{
if (errno != EEXIST)
{
fatal("ERROR: cannot create '%s' folder\n", path);
}
}
}
sys_file sys_open(const char* fname, uint64_t* size)
{
int fd = open(fname, O_RDONLY);
@@ -142,6 +171,18 @@ void sys_write(sys_file file, uint64_t offset, const void* buffer, uint32_t size
#endif
void sys_mkdir(const char* path)
{
char* last = strrchr(path, '/');
if (last)
{
*last = 0;
sys_mkdir(path);
*last = '/';
}
sys_mkdir_real(path);
}
void* sys_realloc(void* ptr, size_t size)
{
void* result = NULL;
@@ -170,3 +211,15 @@ void* sys_realloc(void* ptr, size_t size)
return result;
}
void sys_vstrncat(char* dst, size_t n, const char* format, ...)
{
char temp[1024];
va_list args;
va_start(args, format);
vsnprintf(temp, sizeof(temp), format, args);
va_end(args);
strncat(dst, temp, n - strlen(dst) - 1);
}
+4
View File
@@ -5,6 +5,8 @@
typedef void* sys_file;
void sys_mkdir(const char* path);
sys_file sys_open(const char* fname, uint64_t* size);
sys_file sys_create(const char* fname);
void sys_close(sys_file file);
@@ -15,3 +17,5 @@ void sys_write(sys_file file, uint64_t offset, const void* buffer, uint32_t size
// if ptr && !size => free
// if ptr && size => realloc
void* sys_realloc(void* ptr, size_t size);
void sys_vstrncat(char* dst, size_t n, const char* format, ...);
+6 -4
View File
@@ -1,8 +1,6 @@
#if defined(__MINGW32__) && !defined(__x86_64__)
# define _USE_32BIT_TIME_T
# define __CRT__NO_INLINE
#elif defined(_MSC_VER)
# define _CRT_SECURE_NO_DEPRECATE
#endif
#include "pkg2zip_zip.h"
@@ -102,7 +100,7 @@ void zip_create(zip* z, const char* name)
void zip_add_folder(zip* z, const char* name)
{
size_t name_length = strlen(name);
size_t name_length = strlen(name) + 1;
if (name_length > ZIP_MAX_FILENAME)
{
fatal("ERROR: dirname too long\n");
@@ -131,7 +129,11 @@ void zip_add_folder(zip* z, const char* name)
z->total += sizeof(header);
sys_write(z->file, z->total, name, (uint16_t)name_length);
z->total += name_length;
z->total += name_length - 1;
char slash = '/';
sys_write(z->file, z->total, &slash, 1);
z->total += 1;
}
void zip_begin_file(zip* z, const char* name)