updated unpack-pbp and pack-pbp

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
flatwhatson
Posts: 3
Joined: Fri Dec 29, 2006 1:19 pm
Location: Brisbane, Australia

updated unpack-pbp and pack-pbp

Post by flatwhatson »

Hi everyone,

I'm sure many here have been playing with these new PSX eboots for the PSP... I was finding, because they're quite large, that the unpack-pbp and pack-pbp that come with the pspsdk were hogging all my virtual memory, because they don't implement any kind of buffer size limitations.

So I went ahead and rewrote both of them to use a 16mb maximum read/write buffer, plus a couple of other, minor things. It's all at the top of the code...

Hope you guys like my work, let me know.

flatwhatson

unpack-pbp.c

Code: Select all

/*
# _____     ___ ____     ___ ____
#  ____|   |    ____|   |        | |____|
# |     ___|   |     ___|    ____| |    \    PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# &#40;c&#41; 2005 Dan Peori <peori@oopo.net>
# Licenced under Academic Free License version 2.0
# Review pspsdk README & LICENSE files for further details.
#
# 2006-12-26 - Andrew Whatson <whatson@gmail.com>
#	- rewrote for easier reading
#	- gave "correct" names to UNKNOWN.* files
#	- improved memory efficiency with large PBPs
#	- no longer outputs empty files
#
# $Id&#58; unpack-pbp.c 499 2005-07-05 12&#58;43&#58;35Z mc $
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>

#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif

#ifdef WORDS_BIGENDIAN

// Swap the bytes of an int for big-endian machines
static int swap_int&#40;int n&#41;
&#123;
	return &#40;&#40;n >> 24&#41; & 0xff&#41; | &#40;&#40;n >> 8&#41; & 0xff00&#41; | &#40;&#40;n << 8&#41; & 0xff0000&#41; | &#40;&#40;n << 24&#41; & 0xff000000&#41;;
&#125;

#endif

// Struct to describe the header of a PBP file
typedef struct &#123;
	char	signature&#91;4&#93;;
	int		version;
	int		offset&#91;8&#93;;
&#125; HEADER;

// Correct PBP signature
char correct_sig&#91;4&#93; = &#123;
	0x00,
	0x50,	// P
	0x42,	// B
	0x50	// P
&#125;;

// Names of files included in a PBP
char *filename&#91;8&#93; = &#123;
	"PARAM.SFO",
	"ICON0.PNG",
	"ICON1.PMF",
	"PIC0.PNG",
	"PIC1.PNG",
	"SND0.AT3",
	"DATA.PSP",
	"DATA.PSAR"
&#125;;

// Maximum size of read buffer
int maxbuffer = 16 * 1024 * 1024;

int main&#40;int argc, char *argv&#91;&#93;&#41; &#123;
	FILE *infile;
	FILE *outfile;
	HEADER header;
	int loop0;
	int total_size;
	
	// Check for the correct number of arguments
	if &#40;argc != 2&#41; &#123;
		printf&#40;"USAGE&#58; %s <filename>\n", argv&#91;0&#93;&#41;;
		return -1;
	&#125;
	
	// Open the specified PBP
	infile = fopen&#40;argv&#91;1&#93;, "rb"&#41;;
	if &#40;infile == NULL&#41; &#123;
		printf&#40;"ERROR&#58; Could not open the input file. &#40;%s&#41;\n", argv&#91;1&#93;&#41;;
		return -1;
	&#125;
	
	// Get the size of the PBP
	fseek&#40;infile, 0, SEEK_END&#41;;
	total_size = ftell&#40;infile&#41;;
	fseek&#40;infile, 0, SEEK_SET&#41;;
	if &#40;total_size < 0&#41; &#123;
		printf&#40;"ERROR&#58; Could not get the input file size.\n"&#41;;
		return -1;
	&#125;
	
	// Read in the header
	if &#40;fread&#40;&header, sizeof&#40;HEADER&#41;, 1, infile&#41; < 0&#41; &#123;
		printf&#40;"ERROR&#58; Could not read the input file header.\n"&#41;;
		return -1;
	&#125;
	
	// Check the signature
	for &#40;loop0 = 0; loop0 < sizeof&#40;correct_sig&#41;; loop0++&#41; &#123;
		if &#40;header.signature&#91;loop0&#93; != correct_sig&#91;loop0&#93;&#41; &#123;
			printf&#40;"ERROR&#58; Input file is not a PBP file.\n"&#41;;
			return -1;
		&#125;
	&#125;
	
#ifdef WORDS_BIGENDIAN
	
	// Swap the bytes of the offsets for big-endian machines
	for &#40;loop0 = 0; loop0 < 8; loop0++&#41; &#123;
		header.offset&#91;loop0&#93; = swap_int&#40;header.offset&#91;loop0&#93;&#41;;
	&#125;
	
#endif 
	
	// For each file in the PBP
	for &#40;loop0 = 0; loop0 < 8; loop0++&#41; &#123;
		void *buffer;
		int size;
		
		// Get the size of this file
		if &#40;loop0 == 7&#41; &#123;
			size = total_size - header.offset&#91;loop0&#93;;
		&#125; else &#123;
			size = header.offset&#91;loop0 + 1&#93; - header.offset&#91;loop0&#93;;
		&#125;
		
		// Print out the file details
		printf&#40;"&#91;%d&#93; %10d bytes | %s\n", loop0, size, filename&#91;loop0&#93;&#41;;
		
		// Skip the file if empty
		if &#40;!size&#41; continue;
		
		// Open the output file
		outfile = fopen&#40;filename&#91;loop0&#93;, "wb"&#41;;
		if &#40;outfile == NULL&#41; &#123;
			printf&#40;"ERROR&#58; Could not open the output file. &#40;%s&#41;\n", filename&#91;loop0&#93;&#41;;
			return -1;
		&#125;
		
		do &#123;
			int readsize;
			
			// Make sure we don't exceed the maximum buffer size
			if &#40;size > maxbuffer&#41; &#123;
				readsize = maxbuffer;
			&#125; else &#123;
				readsize = size;
			&#125;
			size -= readsize;
			
			// Create the read buffer
			buffer = malloc&#40;readsize&#41;;
			if &#40;buffer == NULL&#41; &#123;
				printf&#40;"ERROR&#58; Could not allocate the section data buffer. &#40;%d&#41;\n", readsize&#41;;
				return -1;
			&#125;
			
			// Read in the data from the PBP
			if &#40;fread&#40;buffer, readsize, 1, infile&#41; < 0&#41; &#123;
				printf&#40;"ERROR&#58; Could not read in the section data.\n"&#41;;
				return -1;
			&#125;
			
			// Write the contents of the buffer to the output file
			if &#40;fwrite&#40;buffer, readsize, 1, outfile&#41; < 0&#41; &#123;
				printf&#40;"ERROR&#58; Could not write out the section data.\n"&#41;;
				return -1;
			&#125;
			
			// Clean up the buffer
			free&#40;buffer&#41;;
			
			// Repeat if we haven't finished writing the file
		&#125; while &#40;size&#41;;
		
		// Close the output file
		if &#40;fclose&#40;outfile&#41; < 0&#41; &#123;
			printf&#40;"ERROR&#58; Could not close the output file.\n"&#41;;
			return -1;
		&#125;
		
	&#125;
	
	// Close the PBP
	if &#40;fclose&#40;infile&#41; < 0&#41; &#123;
		printf&#40;"ERROR&#58; Could not close the input file.\n"&#41;;
		return -1;
	&#125;
	
	// Exit successful
	return 0;
&#125;
pack-pbp.c

Code: Select all

/*
# _____     ___ ____     ___ ____
#  ____|   |    ____|   |        | |____|
# |     ___|   |     ___|    ____| |    \    PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# &#40;c&#41; 2005 Dan Peori <peori@oopo.net>
# Licenced under Academic Free License version 2.0
# Review pspsdk README & LICENSE files for further details.
#
# 2006-12-30 - Andrew Whatson <whatson@gmail.com>
#	- rewrote for easier reading
#	- gave "correct" names to UNKNOWN.* files
#	- improved memory efficiency with large PBPs
#   - output name of each file as it's added
#
# $Id&#58; pack-pbp.c 499 2005-07-05 12&#58;43&#58;35Z mc $
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef WORDS_BIGENDIAN

// Swap the bytes of an int for big-endian machines
static int swap_int&#40;int n&#41;
&#123;
  return &#40;&#40;n>>24&#41;&0xff&#41;|&#40;&#40;n>>8&#41;&0xff00&#41;|&#40;&#40;n<<8&#41;&0xff0000&#41;|&#40;&#40;n<<24&#41;&0xff000000&#41;;
&#125;

#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef HAVE_MALLOC_H 
#include <malloc.h> 
#endif 

// Struct to describe the header of a PBP file
struct &#123;
	char signature&#91;4&#93;;
	char version&#91;4&#93;;
	int offset&#91;8&#93;;
&#125; header = &#123;
	&#123; 0x00, 0x50, 0x42, 0x50 &#125;,
	&#123; 0x00, 0x00, 0x01, 0x00 &#125;,
	&#123; 40, 0, 0, 0, 0, 0, 0, 0 &#125;
&#125;;

// Maximum size of read buffer
int maxbuffer = 16 * 1024 * 1024;

int main&#40;int argc, char *argv&#91;&#93;&#41; &#123; int loop0, result;
	FILE *infile;
	FILE *outfile;
	int filesize&#91;8&#93;;
	
	// Check for the correct number of arguments
	if &#40;argc != 10&#41; &#123;
		printf&#40;"USAGE&#58; %s <output.pbp> <param.sfo> <icon0.png> <icon1.pmf> <pic0.png> <pic1.png> <snd0.at3> <data.psp> <data.psar>\n", argv&#91;0&#93;&#41;;
		return -1;
	&#125;
	
	// For each file in the PBP
	for &#40;loop0 = 0; loop0 < 8; loop0++&#41; &#123;
		
		// If the specificed filename is NULL or -, skip the file.
		if &#40;strncmp&#40;argv&#91;2 + loop0&#93;, "NULL", 4&#41; == 0 || strncmp&#40;argv&#91;2 + loop0&#93;, "-", 4&#41; == 0&#41; &#123;
			filesize&#91;loop0&#93; = 0;
		&#125; else &#123;
			
			// Open the file
			infile = fopen&#40;argv&#91;2 + loop0&#93;, "rb"&#41;;
			if &#40;infile == NULL&#41; &#123;
				printf&#40;"ERROR&#58; Could not open the file. &#40;%s&#41;\n", argv&#91;2 + loop0&#93;&#41;;
				return -1;
			&#125;
			
			// Read in the file size
			fseek&#40;infile, 0, SEEK_END&#41;;
			filesize&#91;loop0&#93; = ftell&#40;infile&#41;;
			fseek&#40;infile, 0, SEEK_SET&#41;;
			if &#40;filesize&#91;loop0&#93; < 0&#41; &#123;
				printf&#40;"ERROR&#58; Could not read in the file size. &#40;%s&#41;\n", argv&#91;2 + loop0&#93;&#41;;
				return -1;
			&#125;
			
			// Close the file
			result = fclose&#40;infile&#41;;
			if &#40;result < 0&#41; &#123;
				printf&#40;"ERROR&#58; Could not close the file. &#40;%s&#41;\n", argv&#91;2 + loop0&#93;&#41;;
				return -1;
			&#125;
		&#125;
	&#125;

	// Set the header offset values for each file
	for &#40;loop0 = 1; loop0 < 8; loop0++&#41; &#123;
		header.offset&#91;loop0&#93; = header.offset&#91;loop0 - 1&#93; + filesize&#91;loop0 - 1&#93;;
	&#125;
	
#ifdef WORDS_BIGENDIAN
	
	// Swap the bytes of the offsets for big-endian machines
	for &#40;loop0 = 0; loop0 < 8; loop0++&#41; &#123;
		header.offset&#91;loop0&#93; = swap_int&#40;header.offset&#91;loop0&#93;&#41;;
	&#125;
	
#endif
	
	// Open the output file
	outfile = fopen&#40;argv&#91;1&#93;, "wb"&#41;;
	if &#40;outfile == NULL&#41; &#123;
		printf&#40;"ERROR&#58; Could not open the output file. &#40;%s&#41;\n", argv&#91;1&#93;&#41;;
		return -1;
	&#125;
	
	// Write out the header
	result = fwrite&#40;&header, sizeof&#40;header&#41;, 1, outfile&#41;;
	if &#40;result < 0&#41; &#123;
		printf&#40;"ERROR&#58; Could not write out the file header. &#40;%s&#41;\n", argv&#91;1&#93;&#41;;
		return -1;
	&#125;
	
	// For each file in the PBP
	for &#40;loop0 = 0; loop0 < 8; loop0++&#41; &#123;
		void *buffer;
		int readsize;
		
		// Print out the file details
		printf&#40;"&#91;%d&#93; %10d bytes | %s\n", loop0, filesize&#91;loop0&#93;, argv&#91;2 + loop0&#93;&#41;;
		
		// If this file is empty, skip it
		if &#40;!filesize&#91;loop0&#93;&#41; continue;
		
		// Open the file
		infile = fopen&#40;argv&#91;2 + loop0&#93;, "rb"&#41;;
		if &#40;infile == NULL&#41; &#123;
			printf&#40;"ERROR&#58; Could not open the file. &#40;%s&#41;\n", argv&#91;2 + loop0&#93;&#41;;
			return -1;
		&#125;
		
		do &#123;
			// Make sure we don't exceed the maximum buffer size
			if &#40;filesize&#91;loop0&#93; > maxbuffer&#41; &#123;
				readsize = maxbuffer;
			&#125; else &#123;
				readsize = filesize&#91;loop0&#93;;
			&#125;
			filesize&#91;loop0&#93; -= readsize;
			
			// Create the read buffer
			buffer = malloc&#40;readsize&#41;;
			if &#40;buffer == NULL&#41; &#123;
				printf&#40;"ERROR&#58; Could not allocate the file data space. &#40;%s&#41;\n", argv&#91;2 + loop0&#93;&#41;;
				return -1;
			&#125;
			
			// Read in the data from the file
			if &#40;fread&#40;buffer, readsize, 1, infile&#41; < 0&#41; &#123;
				printf&#40;"ERROR&#58; Could not read in the file data. &#40;%s&#41;\n", argv&#91;2 + loop0&#93;&#41;;
				return -1;
			&#125;
			
			// Write the contents of the buffer to the PBP
			if &#40;fwrite&#40;buffer, readsize, 1, outfile&#41; < 0&#41; &#123;
				printf&#40;"ERROR&#58; Could not write out the file data. &#40;%s&#41;\n", argv&#91;1&#93;&#41;;
				return -1;
			&#125;
			
			// Clean up the buffer
			free&#40;buffer&#41;;
			
			// Repeat if we haven't finished writing the file
		&#125; while &#40;filesize&#91;loop0&#93;&#41;;
	&#125;
	
	// Close the output file.
	result = fclose&#40;outfile&#41;;
	if &#40;result < 0&#41; &#123;
		printf&#40;"ERROR&#58; Could not close the output file. &#40;%s&#41;\n", argv&#91;1&#93;&#41;;
		return -1;
	&#125;
	
	// Exit successful
	return 0;
&#125;
ooPo
Site Admin
Posts: 2023
Joined: Sat Jan 17, 2004 9:56 am
Location: Canada
Contact:

Post by ooPo »

Changes added to the repository.
Post Reply