Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Copyright (c) 2013 xerpi
- /*
- Fast and simple PS4 PUP extractor
- Thanks to SKFU for the PUP information analysis
- Version 3, may have lots of bugs (coded fast)
- I'm not even sure if this will work on Big Endian machines...
- Also thanks to flatz for answering my silly questions :P
- Compiling:
- gcc -o ps4pupextractor ps4pupextractor.c
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #define PS4_PUP_MAGIC 0x32424C53
- #define PS4_PUP_HEADER_SIZE 32 //Until PUP entries
- #define PS4_PUP_ENTRY_SIZE 48 //PUP entry size
- #define COPY_BUFFER_SIZE 1024
- struct ps4pup_pup_info {
- uint32_t offset;
- uint32_t content_size;
- uint64_t reserved;
- uint8_t filename[32];
- } __attribute__((packed));
- struct ps4pup_header {
- uint32_t magic;
- uint64_t version;
- uint32_t file_count;
- uint32_t block_count;
- uint8_t reserved1[12];
- struct ps4pup_pup_info *pups;
- uint8_t reserved2[288];
- } __attribute__((packed));
- int ps4pup_read_header(FILE *fd, struct ps4pup_header *header);
- void ps4pup_free_header(struct ps4pup_header *header);
- int ps4pup_extract(FILE *fd, struct ps4pup_header *header);
- void ps4pup_print_header(const struct ps4pup_header *header);
- void print_usage(void);
- int main (int argc, char *argv[])
- {
- if (argc < 2) {
- print_usage();
- goto exit_error;
- }
- FILE *fd;
- if ((fd = fopen(argv[1], "rb")) == NULL ) {
- printf ("Could not open %s\n", argv[1]);
- goto exit_close;
- }
- struct ps4pup_header h;
- memset(&h, 0, sizeof(struct ps4pup_header));
- if (!ps4pup_read_header(fd, &h)) {
- printf("Error reading PUP file\n");
- goto exit_close;
- }
- ps4pup_print_header(&h);
- printf("\nExtracting PUP files...\n");
- if (!ps4pup_extract(fd, &h)) {
- printf("Error extracting PUP files\n");
- ps4pup_free_header(&h);
- goto exit_close;
- }
- printf("Done!\n");
- ps4pup_free_header(&h);
- return 1;
- exit_close:
- fclose(fd);
- exit_error:
- return EXIT_FAILURE;
- }
- int ps4pup_read_header(FILE *fd, struct ps4pup_header *header)
- {
- if (fd == NULL || header == NULL) {
- return 0;
- }
- fseek(fd, 0, SEEK_SET);
- if (fread((void*)header, 1, PS4_PUP_HEADER_SIZE, fd) != PS4_PUP_HEADER_SIZE) {
- printf("Error reading PUP header");
- return 0;
- }
- if (header->magic != PS4_PUP_MAGIC) {
- printf("This is not a PUP file!\n");
- return 0;
- }
- header->pups = malloc (header->file_count * sizeof(struct ps4pup_pup_info));
- int i;
- for (i = 0; i < header->file_count; ++i) {
- if (fread((void*)&header->pups[i], 1, PS4_PUP_ENTRY_SIZE, fd) != PS4_PUP_ENTRY_SIZE) {
- printf("Error reading PUP entry %i\n", i+1);
- return 0;
- }
- }
- return 1;
- }
- void ps4pup_free_header(struct ps4pup_header *header)
- {
- if (header) {
- if (header->pups) {
- free(header->pups);
- }
- }
- }
- int ps4pup_extract(FILE *fd, struct ps4pup_header *header)
- {
- if (fd == NULL || header == NULL) {
- return 0;
- }
- FILE *pup_out;
- uint8_t copy_buffer[COPY_BUFFER_SIZE];
- int data_offset = PS4_PUP_HEADER_SIZE + PS4_PUP_ENTRY_SIZE * header->file_count;
- data_offset = (data_offset+511) & ~511; //Align to 512 bytes
- int i;
- for (i = 0; i < header->file_count; ++i) {
- fseek(fd, data_offset + header->pups[i].offset, SEEK_SET);
- pup_out = fopen(header->pups[i].filename, "wb");
- int copy_size = header->pups[i].content_size;
- printf(" Extracting PUP %i...", i+1);
- while (copy_size > 0) {
- if (copy_size > COPY_BUFFER_SIZE) {
- if (fread(copy_buffer, 1, COPY_BUFFER_SIZE, fd) != COPY_BUFFER_SIZE) {
- printf("Error, skipping PUP\n");
- break;
- }
- fwrite(copy_buffer, 1, COPY_BUFFER_SIZE, pup_out);
- copy_size -= COPY_BUFFER_SIZE;
- } else {
- if (fread(copy_buffer, 1, copy_size, fd) != copy_size) {
- printf("Error, skipping PUP\n");
- break;
- }
- fwrite(copy_buffer, 1, copy_size, pup_out);
- copy_size = 0;
- }
- }
- printf("Done!\n");
- fsync(fileno(pup_out));
- fclose(pup_out);
- }
- return 1;
- }
- void ps4pup_print_header(const struct ps4pup_header *header)
- {
- char magic_string[5];
- strncpy(magic_string, (char*)(uintptr_t)(&header->magic), 4);
- magic_string[4] = '\0';
- printf("Magic: 0x%X %s\n", header->magic, magic_string);
- printf("Version: %lu\n", header->version);
- printf("File count: %i\n", header->file_count);
- printf("Block count: %i\n", header->block_count);
- int i;
- for (i = 0; i < header->file_count; ++i) {
- printf("PUP %i:\n", i+1);
- printf(" Offset: 0x%X\n", header->pups[i].offset);
- printf(" Size: %i\n", header->pups[i].content_size);
- printf(" Filename: %s\n", header->pups[i].filename);
- }
- }
- void print_usage(void)
- {
- printf("Usage:\nps4pupextractor <PS4UPDATE.PUP>\n");
- printf("It will extract the PUPs as: PS4UPDATEX.PUP being X the PUP number\n");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement