2 * ApplyPPF3.c (Linux Version)
3 * written by Icarus/Paradox
5 * Big Endian support by Hu Kares.
7 * Applies PPF1.0, PPF2.0 & PPF3.0 Patches (including PPF3.0 Undo support)
8 * Feel free to use this source in and for your own
12 * gcc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE applyppf3_linux.c
20 #include <sys/types.h>
23 #if defined(__APPLE__) || defined (MACOSX)
25 //////////////////////////////////////////////////////////////////////
26 // fseeko is already 64 bit for Darwin/MacOS X!
27 // fseeko64 undefined for Darwin/MacOS X!
29 #define fseeko64 fseeko
31 //////////////////////////////////////////////////////////////////////
32 // ftellko is already 64 bit for Darwin/MacOS X!
33 // ftello64 undefined for Darwin/MacOS X!
35 #define ftello64 ftello
37 //////////////////////////////////////////////////////////////////////
38 // "off_t" is already 64 bit for Darwin/MacOS X!
39 // "__off64_t" undefined for Darwin/MacOS X!
41 typedef off_t __off64_t
;
43 #endif /* __APPLE__ || MACOSX */
45 //////////////////////////////////////////////////////////////////////
46 // Macros for little to big Endian conversion.
50 #define Endian16_Swap(value) (value = (((((unsigned short) value) << 8) & 0xFF00) | \
51 ((((unsigned short) value) >> 8) & 0x00FF)))
53 #define Endian32_Swap(value) (value = (((((unsigned long) value) << 24) & 0xFF000000) | \
54 ((((unsigned long) value) << 8) & 0x00FF0000) | \
55 ((((unsigned long) value) >> 8) & 0x0000FF00) | \
56 ((((unsigned long) value) >> 24) & 0x000000FF)))
58 #define Endian64_Swap(value) (value = (((((unsigned long long) value) << 56) & 0xFF00000000000000ULL) | \
59 ((((unsigned long long) value) << 40) & 0x00FF000000000000ULL) | \
60 ((((unsigned long long) value) << 24) & 0x0000FF0000000000ULL) | \
61 ((((unsigned long long) value) << 8) & 0x000000FF00000000ULL) | \
62 ((((unsigned long long) value) >> 8) & 0x00000000FF000000ULL) | \
63 ((((unsigned long long) value) >> 24) & 0x0000000000FF0000ULL) | \
64 ((((unsigned long long) value) >> 40) & 0x000000000000FF00ULL) | \
65 ((((unsigned long long) value) >> 56) & 0x00000000000000FFULL)))
69 #define Endian16_Swap(value)
70 #define Endian32_Swap(value)
71 #define Endian64_Swap(value)
73 #endif /* __BIG_ENDIAN__ */
75 //////////////////////////////////////////////////////////////////////
76 // Used global variables.
78 char binblock
[1024], ppfblock
[1024];
79 unsigned char ppfmem
[512];
83 //////////////////////////////////////////////////////////////////////
85 int PPFVersion(FILE *ppf
);
86 int OpenFiles(char* file1
, char* file2
);
87 int ShowFileId(FILE *ppf
, int ppfver
);
88 void ApplyPPF1Patch(FILE *ppf
, FILE *bin
);
89 void ApplyPPF2Patch(FILE *ppf
, FILE *bin
);
90 void ApplyPPF3Patch(FILE *ppf
, FILE *bin
, char mode
);
92 int main(int argc
, char **argv
){
94 printf("ApplyPPF v3.0 by =Icarus/Paradox= %s\n", __DATE__
);
96 printf("Big Endian support by =Hu Kares=\n\n"); // <Hu Kares> sum credz
97 #endif /* __BIG_ENDIAN__ */
99 printf("Usage: ApplyPPF <command> <binfile> <patchfile>\n");
100 printf("<Commands>\n");
101 printf(" a : apply PPF1/2/3 patch\n");
102 printf(" u : undo patch (PPF3 only)\n");
104 printf("\nExample: ApplyPPF.exe a game.bin patch.ppf\n");
109 case 'a' : if(OpenFiles(argv
[2], argv
[3])) return(0);
112 if(x
==1){ ApplyPPF1Patch(ppf
, bin
); break; }
113 if(x
==2){ ApplyPPF2Patch(ppf
, bin
); break; }
114 if(x
==3){ ApplyPPF3Patch(ppf
, bin
, APPLY
); break; }
117 case 'u' : if(OpenFiles(argv
[2], argv
[3])) return(0);
121 printf("Undo function is supported by PPF3.0 only\n");
123 ApplyPPF3Patch(ppf
, bin
, UNDO
);
128 printf("Error: unknown command: \"%s\"\n",argv
[1]);
138 //////////////////////////////////////////////////////////////////////
139 // Applies a PPF1.0 patch.
140 void ApplyPPF1Patch(FILE *ppf
, FILE *bin
){
143 unsigned int count
, seekpos
;
147 fseeko64(ppf
, 6,SEEK_SET
); /* Read Desc.line */
148 fread(&desc
, 1, 50, ppf
); desc
[50]=0;
149 printf("Patchfile is a PPF1.0 patch. Patch Information:\n");
150 printf("Description : %s\n",desc
);
151 printf("File_id.diz : no\n");
153 printf("Patching... "); fflush(stdout
);
154 fseeko64(ppf
, 0, SEEK_END
);
158 printf("Patching ... ");
161 printf("reading...\b\b\b\b\b\b\b\b\b\b"); fflush(stdout
);
162 fseeko64(ppf
, seekpos
, SEEK_SET
);
163 fread(&pos
, 1, 4, ppf
);
164 Endian32_Swap (pos
); // <Hu Kares> little to big endian
165 fread(&anz
, 1, 1, ppf
);
166 fread(&ppfmem
, 1, anz
, ppf
);
167 fseeko64(bin
, pos
, SEEK_SET
);
168 printf("writing...\b\b\b\b\b\b\b\b\b\b"); fflush(stdout
);
169 fwrite(&ppfmem
, 1, anz
, bin
);
170 seekpos
=seekpos
+5+anz
;
174 printf("successful.\n");
178 //////////////////////////////////////////////////////////////////////
179 // Applies a PPF2.0 patch.
180 void ApplyPPF2Patch(FILE *ppf
, FILE *bin
){
182 unsigned int binlen
, obinlen
, count
, seekpos
;
188 fseeko64(ppf
, 6,SEEK_SET
);
189 fread(&desc
, 1, 50, ppf
); desc
[50]=0;
190 printf("Patchfile is a PPF2.0 patch. Patch Information:\n");
191 printf("Description : %s\n",desc
);
192 printf("File_id.diz : ");
193 idlen
=ShowFileId(ppf
, 2);
194 if(!idlen
) printf("not available\n");
196 fseeko64(ppf
, 56, SEEK_SET
);
197 fread(&obinlen
, 1, 4, ppf
);
198 Endian32_Swap (obinlen
); // <Hu Kares> little to big endian
199 fseeko64(bin
, 0, SEEK_END
);
202 printf("The size of the bin file isn't correct, continue ? (y/n): "); fflush(stdout
);
204 if(in
!='y'&&in
!='Y'){
205 printf("Aborted...\n");
211 fseeko64(ppf
, 60, SEEK_SET
);
212 fread(&ppfblock
, 1, 1024, ppf
);
213 fseeko64(bin
, 0x9320, SEEK_SET
);
214 fread(&binblock
, 1, 1024, bin
);
215 in
=memcmp(ppfblock
, binblock
, 1024);
217 printf("Binblock/Patchvalidation failed. continue ? (y/n): "); fflush(stdout
);
219 #if defined(__APPLE__) || defined (MACOSX)
221 if(obinlen
!=binlen
) { // <Hu Kares> required, since fflush doesn't flush '\n'!
225 #endif /* __APPLE__ || MACOSX */
228 if(in
!='y'&&in
!='Y'){
229 printf("Aborted...\n");
234 printf("Patching... "); fflush(stdout
);
235 fseeko64(ppf
, 0, SEEK_END
);
239 if(idlen
) count
-=idlen
+38;
242 printf("reading...\b\b\b\b\b\b\b\b\b\b"); fflush(stdout
);
243 fseeko64(ppf
, seekpos
, SEEK_SET
);
244 fread(&pos
, 1, 4, ppf
);
245 Endian32_Swap (pos
); // <Hu Kares> little to big endian
246 fread(&anz
, 1, 1, ppf
);
247 fread(&ppfmem
, 1, anz
, ppf
);
248 fseeko64(bin
, pos
, SEEK_SET
);
249 printf("writing...\b\b\b\b\b\b\b\b\b\b"); fflush(stdout
);
250 fwrite(&ppfmem
, 1, anz
, bin
);
251 seekpos
=seekpos
+5+anz
;
255 printf("successful.\n");
257 //////////////////////////////////////////////////////////////////////
258 // Applies a PPF3.0 patch.
259 void ApplyPPF3Patch(FILE *ppf
, FILE *bin
, char mode
){
260 char desc
[50], imagetype
=0, in
;
261 unsigned char undo
=0, blockcheck
=0;
263 __off64_t offset
, count
; // <Hu Kares> count has to be 64 bit!
264 unsigned int seekpos
;
268 fseeko64(ppf
, 6,SEEK_SET
); /* Read Desc.line */
269 fread(&desc
, 1, 50, ppf
); desc
[50]=0;
270 printf("Patchfile is a PPF3.0 patch. Patch Information:\n");
271 printf("Description : %s\n",desc
);
272 printf("File_id.diz : ");
274 idlen
=ShowFileId(ppf
, 3);
275 if(!idlen
) printf("not available\n");
277 fseeko64(ppf
, 56, SEEK_SET
);
278 fread(&imagetype
, 1, 1, ppf
);
279 fseeko64(ppf
, 57, SEEK_SET
);
280 fread(&blockcheck
, 1, 1, ppf
);
281 fseeko64(ppf
, 58, SEEK_SET
);
282 fread(&undo
, 1, 1, ppf
);
286 printf("Error: no undo data available\n");
293 fseeko64(ppf
, 60, SEEK_SET
);
294 fread(&ppfblock
, 1, 1024, ppf
);
297 fseeko64(bin
, 0x80A0, SEEK_SET
);
299 fseeko64(bin
, 0x9320, SEEK_SET
);
301 fread(&binblock
, 1, 1024, bin
);
302 in
=memcmp(ppfblock
, binblock
, 1024);
304 printf("Binblock/Patchvalidation failed. continue ? (y/n): "); fflush(stdout
);
306 if(in
!='y'&&in
!='Y'){
307 printf("Aborted...\n");
313 fseeko64(ppf
, 0, SEEK_END
);
314 count
=ftello64(ppf
); // <Hu Kares> 64 bit!
315 fseeko64(ppf
, 0, SEEK_SET
);
325 if(idlen
) count
-=(idlen
+18+16+2);
328 printf("Patching ... ");
329 fseeko64(ppf
, seekpos
, SEEK_SET
);
331 printf("reading...\b\b\b\b\b\b\b\b\b\b"); fflush(stdout
);
332 fread(&offset
, 1, 8, ppf
);
333 Endian64_Swap(offset
); // <Hu Kares> little to big endian
334 fread(&anz
, 1, 1, ppf
);
337 fread(&ppfmem
, 1, anz
, ppf
);
338 if(undo
) fseeko64(ppf
, anz
, SEEK_CUR
);
342 fseeko64(ppf
, anz
, SEEK_CUR
);
343 fread(&ppfmem
, 1, anz
, ppf
);
347 printf("writing...\b\b\b\b\b\b\b\b\b\b"); fflush(stdout
);
348 fseeko64(bin
, offset
, SEEK_SET
);
349 fwrite(&ppfmem
, 1, anz
, bin
);
355 printf("successful.\n");
360 //////////////////////////////////////////////////////////////////////
361 // Shows File_Id.diz of a PPF2.0 / PPF3.0 patch.
364 // Return 0 = Error/no fileid.
365 // Return>0 = Length of fileid.
366 int ShowFileId(FILE *ppf
, int ppfver
){
368 unsigned int idmagic
;
369 int lenidx
=0, idlen
=0, orglen
=0;
378 fseeko64(ppf
,-(lenidx
+4),SEEK_END
);
379 fread(&idmagic
, 1, 4, ppf
);
380 Endian32_Swap (idmagic
); // <Hu Kares> little to big endian
384 fseeko64(ppf
,-lenidx
,SEEK_END
);
385 fread(&idlen
, 1, lenidx
, ppf
);
386 Endian32_Swap (idlen
); // <Hu Kares> little to big endian
388 if (idlen
> 3072) { // <Hu Kares> to be secure: avoid segmentation fault!
391 fseeko64(ppf
,-(lenidx
+16+idlen
),SEEK_END
);
392 fread(&buffer2
, 1, idlen
, ppf
);
394 printf("available\n%s\n",buffer2
);
400 //////////////////////////////////////////////////////////////////////
401 // Check what PPF version we have.
402 // Return: 0 - File is no PPF.
403 // Return: 1 - File is a PPF1.0
404 // Return: 2 - File is a PPF2.0
405 // Return: 3 - File is a PPF3.0
406 int PPFVersion(FILE *ppf
){
409 fseeko64(ppf
,0,SEEK_SET
);
410 fread(&magic
, 1, 4, ppf
);
411 Endian32_Swap (magic
); // <Hu Kares> little to big endian
413 case '1FPP' : return(1);
414 case '2FPP' : return(2);
415 case '3FPP' : return(3);
416 default : printf("Error: patchfile is no ppf patch\n"); break;
423 //////////////////////////////////////////////////////////////////////
424 // Open all needed files.
425 // Return: 0 - Successful
426 // Return: 1 - Failed.
427 int OpenFiles(char* file1
, char* file2
){
429 bin
=fopen(file1
, "rb+");
431 printf("Error: cannot open file '%s' ",file1
);
435 ppf
=fopen(file2
, "rb");
437 printf("Error: cannot open file '%s' ",file2
);