-
Notifications
You must be signed in to change notification settings - Fork 8
/
unpack-pbp.c
167 lines (142 loc) · 4.02 KB
/
unpack-pbp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 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: unpack-pbp.c 2228 2007-05-01 05:22:03Z oopo $
*/
#include <stdio.h>
#include <stdlib.h>
#ifndef __APPLE__
#include <malloc.h>
#else
#include <malloc/malloc.h>
#endif
#include "unpack-pbp.h"
#ifdef WORDS_BIGENDIAN
// Swap the bytes of an int for big-endian machines
static int swap_int(int n) {
return ((n >> 24) & 0xff) | ((n >> 8) & 0xff00) | ((n << 8) & 0xff0000) | ((n << 24) & 0xff000000);
}
#endif
int maxunpackbuffer = 16 * 1024 * 1024;
// Correct PBP signature
char correct_sig[4] = {
0x00,
0x50, // P
0x42, // B
0x50 // P
};
// Names of files included in a PBP
char *filename[8] = {
"param.sfo",
"icon0.png",
"icon1.pmf",
"pic0.png",
"pic1.png",
"snd0.at3",
"data_unsigned.psp",
"data.psar"
};
int unpack_pbp(FILE *infile) {
FILE *outfile;
HEADER header;
int loop0;
int total_size;
// Get the size of the PBP
fseek(infile, 0, SEEK_END);
total_size = ftell(infile);
fseek(infile, 0, SEEK_SET);
if (total_size < 0) {
printf("ERROR: Could not get the input file size.\n");
return -1;
}
// Read in the header
if (fread(&header, sizeof(HEADER), 1, infile) < 0) {
printf("ERROR: Could not read the input file header.\n");
return -1;
}
// Check the signature
for (loop0 = 0; loop0 < sizeof(correct_sig); loop0++) {
if (header.signature[loop0] != correct_sig[loop0]) {
printf("ERROR: Input file is not a PBP file.\n");
return -1;
}
}
#ifdef WORDS_BIGENDIAN
// Swap the bytes of the offsets for big-endian machines
for (loop0 = 0; loop0 < 8; loop0++) {
header.offset[loop0] = swap_int(header.offset[loop0]);
}
#endif
// For each file in the PBP
for (loop0 = 0; loop0 < 8; loop0++) {
void *buffer;
int size;
// Get the size of this file
if (loop0 == 7) {
size = total_size - header.offset[loop0];
} else {
size = header.offset[loop0 + 1] - header.offset[loop0];
}
// Skip the file if empty
if (!size) continue;
// Open the output file
outfile = fopen(filename[loop0], "wb");
if (outfile == NULL) {
printf("\nERROR: Could not open the output file. (%s)\n", filename[loop0]);
return -1;
}
do {
int readsize;
// Make sure we don't exceed the maximum buffer size
if (size > maxunpackbuffer) {
readsize = maxunpackbuffer;
} else {
readsize = size;
}
size -= readsize;
// Create the read buffer
buffer = malloc(readsize);
if (buffer == NULL) {
printf("\nERROR: Could not allocate the section data buffer. (%d)\n", readsize);
return -1;
}
// Read in the data from the PBP
if (fread(buffer, readsize, 1, infile) < 0) {
printf("\nERROR: Could not read in the section data.\n");
return -1;
}
// Write the contents of the buffer to the output file
if (fwrite(buffer, readsize, 1, outfile) < 0) {
printf("\nERROR: Could not write out the section data.\n");
return -1;
}
// Clean up the buffer
free(buffer);
// Repeat if we haven't finished writing the file
} while (size);
// Close the output file
if (fclose(outfile) < 0) {
printf("\nERROR: Could not close the output file.\n");
return -1;
}
}
// Close the PBP
if (fclose(infile) < 0) {
printf("ERROR: Could not close the input file.\n");
return -1;
}
// Exit successful
return 0;
}