mirror of
https://github.com/mmozeiko/pkg2zip.git
synced 2026-09-02 19:23:09 +03:00
add -x argument to create individual files without zip file
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user