updated on Mon Jan 23 12:00:23 UTC 2012
[aur-mirror.git] / applyppf / applyppf3_linux.c
blob840ff47d87ce67c51d999b742016a04e3bcc6eb3
1 /*
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
9 * programms.
11 * To compile enter:
12 * gcc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE applyppf3_linux.c
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/stat.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.
48 #ifdef __BIG_ENDIAN__
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)))
67 #else
69 #define Endian16_Swap(value)
70 #define Endian32_Swap(value)
71 #define Endian64_Swap(value)
73 #endif /* __BIG_ENDIAN__ */
75 //////////////////////////////////////////////////////////////////////
76 // Used global variables.
77 FILE *ppf, *bin;
78 char binblock[1024], ppfblock[1024];
79 unsigned char ppfmem[512];
80 #define APPLY 1
81 #define UNDO 2
83 //////////////////////////////////////////////////////////////////////
84 // Used prototypes.
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){
93 int x;
94 printf("ApplyPPF v3.0 by =Icarus/Paradox= %s\n", __DATE__);
95 #ifdef __BIG_ENDIAN__
96 printf("Big Endian support by =Hu Kares=\n\n"); // <Hu Kares> sum credz
97 #endif /* __BIG_ENDIAN__ */
98 if(argc!=4){
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");
105 return(0);
108 switch(*argv[1]){
109 case 'a' : if(OpenFiles(argv[2], argv[3])) return(0);
110 x=PPFVersion(ppf);
111 if(x){
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; }
115 } else{ break; }
116 break;
117 case 'u' : if(OpenFiles(argv[2], argv[3])) return(0);
118 x=PPFVersion(ppf);
119 if(x){
120 if(x!=3){
121 printf("Undo function is supported by PPF3.0 only\n");
122 } else {
123 ApplyPPF3Patch(ppf, bin, UNDO);
125 } else{ break; }
126 break;
127 default :
128 printf("Error: unknown command: \"%s\"\n",argv[1]);
129 return(0);
130 break;
133 fclose(bin);
134 fclose(ppf);
135 return(0);
138 //////////////////////////////////////////////////////////////////////
139 // Applies a PPF1.0 patch.
140 void ApplyPPF1Patch(FILE *ppf, FILE *bin){
141 char desc[50];
142 int pos;
143 unsigned int count, seekpos;
144 unsigned char anz;
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);
155 count=ftell(ppf);
156 count-=56;
157 seekpos=56;
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;
171 count=count-5-anz;
172 } while(count!=0);
174 printf("successful.\n");
178 //////////////////////////////////////////////////////////////////////
179 // Applies a PPF2.0 patch.
180 void ApplyPPF2Patch(FILE *ppf, FILE *bin){
181 char desc[50], in;
182 unsigned int binlen, obinlen, count, seekpos;
183 int idlen, pos;
184 unsigned char anz;
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);
200 binlen=ftell(bin);
201 if(obinlen!=binlen){
202 printf("The size of the bin file isn't correct, continue ? (y/n): "); fflush(stdout);
203 in=getc(stdin);
204 if(in!='y'&&in!='Y'){
205 printf("Aborted...\n");
206 return;
210 fflush(stdin);
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);
216 if(in!=0){
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'!
222 in=getc(stdin);
225 #endif /* __APPLE__ || MACOSX */
227 in=getc(stdin);
228 if(in!='y'&&in!='Y'){
229 printf("Aborted...\n");
230 return;
234 printf("Patching... "); fflush(stdout);
235 fseeko64(ppf, 0, SEEK_END);
236 count=ftell(ppf);
237 seekpos=1084;
238 count-=1084;
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;
252 count=count-5-anz;
253 } while(count!=0);
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;
262 int idlen;
263 __off64_t offset, count; // <Hu Kares> count has to be 64 bit!
264 unsigned int seekpos;
265 unsigned char anz=0;
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);
284 if(mode==UNDO){
285 if(!undo){
286 printf("Error: no undo data available\n");
287 return;
291 if(blockcheck){
292 fflush(stdin);
293 fseeko64(ppf, 60, SEEK_SET);
294 fread(&ppfblock, 1, 1024, ppf);
296 if(imagetype){
297 fseeko64(bin, 0x80A0, SEEK_SET);
298 } else {
299 fseeko64(bin, 0x9320, SEEK_SET);
301 fread(&binblock, 1, 1024, bin);
302 in=memcmp(ppfblock, binblock, 1024);
303 if(in!=0){
304 printf("Binblock/Patchvalidation failed. continue ? (y/n): "); fflush(stdout);
305 in=getc(stdin);
306 if(in!='y'&&in!='Y'){
307 printf("Aborted...\n");
308 return;
313 fseeko64(ppf, 0, SEEK_END);
314 count=ftello64(ppf); // <Hu Kares> 64 bit!
315 fseeko64(ppf, 0, SEEK_SET);
317 if(blockcheck){
318 seekpos=1084;
319 count-=1084;
320 } else {
321 seekpos=60;
322 count-=60;
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);
336 if(mode==APPLY){
337 fread(&ppfmem, 1, anz, ppf);
338 if(undo) fseeko64(ppf, anz, SEEK_CUR);
340 else {
341 if(mode==UNDO){
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);
350 count-=(anz+9);
351 if(undo) count-=anz;
353 } while(count!=0);
355 printf("successful.\n");
360 //////////////////////////////////////////////////////////////////////
361 // Shows File_Id.diz of a PPF2.0 / PPF3.0 patch.
362 // Input: 2 = PPF2.0
363 // Input: 3 = PPF3.0
364 // Return 0 = Error/no fileid.
365 // Return>0 = Length of fileid.
366 int ShowFileId(FILE *ppf, int ppfver){
367 char buffer2[3073];
368 unsigned int idmagic;
369 int lenidx=0, idlen=0, orglen=0;
372 if(ppfver==2){
373 lenidx=4;
374 } else {
375 lenidx=2;
378 fseeko64(ppf,-(lenidx+4),SEEK_END);
379 fread(&idmagic, 1, 4, ppf);
380 Endian32_Swap (idmagic); // <Hu Kares> little to big endian
381 if(idmagic!='ZID.'){
382 return(0);
383 } else {
384 fseeko64(ppf,-lenidx,SEEK_END);
385 fread(&idlen, 1, lenidx, ppf);
386 Endian32_Swap (idlen); // <Hu Kares> little to big endian
387 orglen = idlen;
388 if (idlen > 3072) { // <Hu Kares> to be secure: avoid segmentation fault!
389 idlen = 3072;
391 fseeko64(ppf,-(lenidx+16+idlen),SEEK_END);
392 fread(&buffer2, 1, idlen, ppf);
393 buffer2[idlen]=0;
394 printf("available\n%s\n",buffer2);
397 return(orglen);
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){
407 unsigned int magic;
409 fseeko64(ppf,0,SEEK_SET);
410 fread(&magic, 1, 4, ppf);
411 Endian32_Swap (magic); // <Hu Kares> little to big endian
412 switch(magic){
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;
419 return(0);
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+");
430 if(!bin){
431 printf("Error: cannot open file '%s' ",file1);
432 return(1);
435 ppf=fopen(file2, "rb");
436 if(!ppf){
437 printf("Error: cannot open file '%s' ",file2);
438 fclose(bin);
439 return(1);
442 return(0);