Upgraded to Pr 1.0 beta
[fp-git.git] / PR / src / console / main.c
1 /*  Princed V3 - Prince of Persia Level Editor for PC Version
2     Copyright (C) 2003 Princed Development Team
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18     The authors of this program may be contacted at http://forum.princed.com.ar
19 */
20
21 /*
22 pr.c: Main source file for Princed Resources
23 ¯¯¯¯
24         Princed Resources editor
25         (c) Copyright 2003, Princed Development Team
26
27         Authors
28          Coding & main routines
29           Enrique Calot
30           Santiago Zamora
31
32          Graphic compression algorithms
33           Tammo Jan Dijkema
34           Enrique Calot
35
36          Graphic format development
37           Tammo Jan Dijkema
38           Anke Balderer
39
40          MID Sound format development
41           Christian Lundheim
42
43          Resources.xml edition
44           Steven Fayers
45
46  Note:
47   DO NOT remove this copyright notice
48 */
49
50 /* Headers */
51 #include <stdio.h>
52 #include <string.h>
53
54 #include "pr.h"
55
56 #include "compress.h"
57
58 #include "extract.h"
59 #include "compile.h"
60 #include "tasks.h"
61
62 #include "memory.h"    /* getMemory, free */
63 #include "disk.h"      /* getFileNameFromPath */
64
65 #ifndef DLL
66  #ifdef UNIX
67   #include <unistd.h>
68   #ifndef LINUX
69    #include "getopt.h"
70   #endif
71  #else
72   #include "getopt.h"
73  #endif
74 #endif
75
76 /***************************************************************\
77 |                      Main working functions                   |
78 \***************************************************************/
79
80 FILE* outputStream=NULL;
81
82 #ifdef DLL
83 void prSetOutput(FILE* output) {
84         outputStream=output;
85 }
86 #endif
87
88 #ifdef DLL
89 int prExportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
90         outputStream=stdout;
91         return prExportDatOpt(vDatFile,vDirName,vResFile,export_flag,NULL,NULL,NULL);
92 }
93 #endif
94
95 int prExportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName,const char* datAuthor, const char* backupExtension) {
96         /*
97                 Arguments:
98                         char* vDatFile        - full Path to the dat file;
99                                                 if file use it, if directory, perform it for
100                                                 all files
101                         char* vDirName        - full Path to the extracting folder
102                                                 (doesn't need to exist)
103                         char* vResFile        - full Path to the resources XML file
104                                                 NULL is the default file resources.xml
105                         char opt              - program options, see below
106                         char* vDatFileName    - name of the file to be extracted
107                                                 NULL means predict it from vDatFile
108                         const char* datAuthor - Author's name when extracting PLV's,
109                                                 NULL is default
110                         const char* backupExtension
111                                               - If backup_flag is set, the string to attach
112                                                 to the backup files
113
114                 Options:
115                         unknown_flag   - generate the unknown file without performing
116                        any extraction
117                         raw_flag       - uses raw format
118                         verbose_flag   - explain what is being done
119                         recursive_flag - searches for all dat files (only if vDatFile
120                                          is not a dat file and vDatFileName is NULL)
121                         force_flag     - default option, you cannot disable it,
122                                          so please make a backup of your files
123                         backup_flag    - backup your files
124
125
126                 Return values:
127                         00 Ok
128                         -1 Error accessing the file DAT
129                         -2 Memory error in extraction
130                         -3 Invalid DAT file
131                         -4 XML Parse error
132                         -5 Memory error in parsing
133                         -6 XML Attribute not recognized
134                         -7 XML File not found
135         */
136
137         /* Declare variables */
138         tResource* r[MAX_RES_COUNT];
139         int a;
140         const char* aux;
141         char* currentDatFileName;
142         char* currentDatFile;
143
144         currentDatFile=strallocandcopy(vDatFileName);
145
146         parseGivenPath(currentDatFile);
147
148         if (vDatFileName==NULL) { /* if no special dat file was specified, a path parsed will be used */
149                 aux=getFileNameFromPath(vDatFile);
150         } else {
151                 aux=currentDatFile;
152         }
153         currentDatFileName=strallocandcopy(aux);
154
155         /* Parse XML and export the file */
156         a=parseFile(vResFile,currentDatFileName,r);
157         if (a<0) {
158                 /* parsing errors */
159                 a-=3;
160         } else {
161                 /* exporting errors/no errors */
162                 a=extract(vDatFile,vDirName,r,opt,currentDatFileName,datAuthor,backupExtension);
163         }
164         free(currentDatFileName);
165         free(currentDatFile);
166         freePartialList();
167
168         return a;
169 }
170
171 #ifdef DLL
172 int prImportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
173         outputStream=stdout;
174         return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL);
175 }
176 #endif
177
178 int prImportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName, const char* backupExtension) {
179         /*
180                 Arguments:
181                         char* vDatFile        - full Path to the dat file;
182                                                 if file use it, if directory, perform it for
183                                                 all files
184                         char* vDirName        - full Path to the extracting folder
185                                                 (doesn't need to exist)
186                         char* vResFile        - full Path to the resources XML file
187                                                 (resources.xml by default)
188                         char opt              - program options, see below
189                         char *vDatFileName    - name of the file to be extracted
190                                                 NULL means predict it from vDatFile
191                         const char* backupExtension
192                                               - If backup_flag is set, the string to attach
193                                                 to the backup files
194
195                 Options:
196                         raw_flag       - uses raw format
197                         verbose_flag   - explain what is being done
198                         recursive_flag - searches for all dat files (only if vDatFile
199                                          is not a dat file and vDatFileName is NULL)
200                         force_flag     - If not set and the file exists it will prompt
201                                          for action
202                         backup_flag    - backup your files
203
204
205                 Return values:
206                         -1 DAT File couldn't be open for writing
207                         -2 XML Parse error
208                         -3 No memory
209                         -4 XML Attribute not recognized
210                         -5 XML File not found
211                         00 File successfully imported
212                         positive number: number of missing files
213         */
214
215         /* Declare variables */
216         tResource* r[MAX_RES_COUNT];
217         int a;
218         const char* aux;
219         char* currentDatFileName;
220
221         if (vDatFileName==NULL) { /* if no special dat file was specified, a path parsed will be used */
222                 aux=getFileNameFromPath(vDatFile);
223         } else {
224                 aux=vDatFileName;
225         }
226         currentDatFileName=strallocandcopy(aux);
227
228         /* Parse XML and import files */
229         a=parseFile(vResFile,currentDatFileName,r);
230         if (a<0) {
231                 /* parsing errors */
232                 a-=1;
233         } else {
234                 /* importing errors/no errors */
235                 a=compile (vDatFile, vDirName,r,opt,currentDatFileName,backupExtension);
236         }
237         free(currentDatFileName);
238         return a;
239 }
240
241 /***************************************************************\
242 |                     M A I N   P R O G R A M                   |
243 \***************************************************************/
244
245 void syntax() {
246         fprintf(outputStream,PARSING_HELP);
247 }
248
249 int prMain(int optionflag, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
250
251         /* declare variables */
252         int returnValue;
253
254         outputStream=output;
255
256         /* do selected tasks */
257         if (hasFlag(export_flag)) { /* Export file */
258                 char* array[]=PR_TEXT_EXPORT_ARRAY;
259                 fprintf(output,PR_TEXT_TASK_EXTRACT,datfile,dirName);
260                 returnValue=prExportDatOpt(datfile,dirName,resFile,optionflag,datfilename,datAuthor,extension);
261                 fprintf(output,PR_TEXT_RESULT,array[-returnValue],returnValue);
262         }       else if (hasFlag(classify_flag)) { /* Classify file */
263                 char* array[]=PR_TEXT_CLASSIFY_ARRAY;
264                 fprintf(output,PR_TEXT_TASK_CLASSIFY,datfile);
265                 returnValue=prVerifyDatType(datfile);
266                 if (hasFlag(cgi_flag)) {
267                         fprintf(output,PR_CGI_TEXT2,returnValue);
268                 } else {
269                         fprintf(output,PR_TEXT_RESULT,array[2+returnValue],returnValue);
270                 }
271         }       else if (hasFlag(import_flag)) { /* Import file */
272                 char* array[]=PR_TEXT_IMPORT_ARRAY;
273                 fprintf(output,PR_TEXT_TASK_COMPILE,datfile,dirName);
274                 returnValue=prImportDatOpt(datfile,dirName,resFile,optionflag,datfilename,extension);
275                 if (returnValue<=0) {
276                         fprintf(output,PR_TEXT_RESULT,array[-returnValue],returnValue);
277                 } else {
278                         fprintf(output,PR_TEXT_RESULT_ERR,returnValue);
279                 }
280         } else {
281                 syntax();
282                 returnValue=-1;
283         }
284
285         return returnValue;
286 }
287
288 #ifndef DLL
289
290 /***************************************************************\
291 |             Standard executable specific functions            |
292 \***************************************************************/
293
294 int prStart(int optionflag, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
295         int result=1;
296         whatIs selectedFile;
297         outputStream=output;
298
299         /* Show about or cgi stuff */
300         if (hasFlag(cgi_flag)) {
301                 fprintf(output,PR_CGI_TEXT1);
302         } else {
303                 fprintf(output,PR_ABOUT);
304         }
305
306         /* Show version screen if requested */
307         if (hasFlag(version_flag)) {
308                 fprintf(output,PARSING_ABOUT);
309                 return -1;
310         }
311
312         /* If bad syntax or help screen requested */
313         if (hasFlag(help_flag)) {
314                 syntax();
315                 return -1;
316         }
317
318         /* Perform tasks depending on the argument */
319         if (hasFlag(import_flag)) {
320                 /* We have to import something, let's see what the parameters are */
321                 if (datfile==NULL) {
322                         /* no files? let's use the whole current directory */
323                         fprintf(output,PR_TEXT_IMPORTING_CURRENT);
324                         importDir(dirName,resFile,optionflag,extension,".",output);
325                 } else if ((selectedFile=isDir(datfile))!=eFile) {
326                         fprintf(output,PR_TEXT_IMPORTING_GIVEN);
327                         if ((selectedFile==eDirectory)||(isntADatFile(getFileNameFromPath(datfile),resFile))) {
328                                 /* it's a directory or doesn't exist (but it's not a dat file) */
329                                 importDir(dirName,resFile,optionflag,extension,datfile,output);
330                         } else {
331                                 /* it doesn't exist but it's a dat file */
332                                 result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
333                         }
334                 } else { /* it's only one existent file */
335                         result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
336                 }
337         } else {
338                 /* We have to export/classify something, perhaps we'll need to use somerecursive functions */
339                 if (datfile==NULL) {
340                         /* If nothing, let's use the current dir and check for all the files there */
341                         fprintf(output,PR_TEXT_SCANNING_CURRENT);
342                         recurseDirectory(".",optionflag,extension,dirName,resFile,datfilename,datAuthor,output);
343                 } else if ((selectedFile=isDir(datfile))==eDirectory) {
344                         /* If it's a directory, let's check for all the files there */
345                         fprintf(output,PR_TEXT_SCANNING_GIVEN);
346                         recurseDirectory(datfile,optionflag,extension,dirName,resFile,datfilename,datAuthor,output);
347                 } else if (selectedFile==eNotFound) {
348                         /* If the file doesn't exist, print an error and exit */
349                         fprintf(output,PR_TEXT_FILE_NOT_FOUND,datfile);
350                         result=0;
351                 } else {
352                         /* If it is a file, just do the tasks for it */
353                         result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
354                 }
355         }
356
357         freeParsedStructure();
358         return result;
359 }
360
361 /***************************************************************\
362 |      Standard executable command line parsing function        |
363 \***************************************************************/
364
365 int main (int argc, char **argv) {
366         /* declare variables */
367         char  dirName[MAX_FILENAME_SIZE]=".";
368         char* datAuthor  =NULL;
369         char* datFileName=NULL;
370         char* datFilePath=NULL;
371         char* extension  =NULL;
372         char* resFile    =NULL;
373         int   c;
374         int   optionflag=0;
375
376         /* Parse command line options */
377         do {
378                 static struct option long_options[] = PARSING_OPTIONS;
379                 int junk = 0;
380
381                 c = getopt_long(argc,argv,PARSING_CHARS,long_options,&junk);
382                 switch (c) {
383                                 case 'c':
384                                 case 'i':
385                                         if (hasFlag(classify_flag|export_flag)) setFlag(help_flag);
386                                         setFlag(import_flag);
387                                         if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
388                                         break;
389                                 case 'g':
390                                         setFlag(cgi_flag); /* if cgi, a classify must be performed */
391                                 case 'd':
392                                         if (hasFlag(import_flag|export_flag)) setFlag(help_flag);
393                                         setFlag(classify_flag);
394                                         break;
395                                 case 'x':
396                                 case 'e':
397                                         if (hasFlag(classify_flag|import_flag)) setFlag(help_flag);
398                                         setFlag(export_flag);
399                                         if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
400                                         break;
401                                 case 'b':
402                                         setFlag(backup_flag);
403                                         freeAllocation(extension);
404                                         extension=strallocandcopy(optarg);
405                                         break;
406                                 case 'f':
407                                         setFlag(force_flag);
408                                         break;
409                                 case 's':
410                                         freeAllocation(resFile);
411                                         resFile=strallocandcopy(optarg);
412                                         break;
413                                 case 'r':
414 #ifndef PR_IGNORE_RAW_OPTION
415                                         setFlag(raw_flag);
416                                         break;
417 #endif
418                                 case 'R':
419                                         setFlag(recursive_flag);
420                                         break;
421                                 case 't':
422                                         freeAllocation(datFileName);
423                                         datFileName=strallocandcopy(optarg);
424                                         break;
425                                 case 'a':
426                                         freeAllocation(datAuthor);
427                                         datAuthor=strallocandcopy(optarg);
428                                         break;
429                                 case 'v':
430                                         setFlag(verbose_flag);
431                                         break;
432                                 case 2:
433                                         setFlag(unknown_flag);
434                                 case -1:
435                                         break;
436                                 case 1:
437                                         setFlag(version_flag);
438                                 default:
439                                         setFlag(help_flag);
440                 }
441         } while (c!=-1);
442
443         if (optind < argc) {
444                 int size;
445                 datFilePath=strallocandcopy(argv[optind]);
446                 /* Erase the last "/" if exists. TODO: send to parseGivenPath  */
447                 size=strlen(datFilePath);
448                 if (size>0) {
449                         size--;
450                         if (isDirSep(datFilePath,size)) datFilePath[size]=0;
451                 }
452         }
453
454         /* At least one of these options must be selected, if not, the user needs help! */
455         if (!(hasFlag(import_flag|export_flag|classify_flag))) setFlag(help_flag);
456
457         parseGivenPath(datFilePath);
458
459         /* Run main program */
460         prStart(optionflag,extension,dirName,resFile,datFilePath,datFileName,datAuthor,stdout);
461
462         /* Free memory and exit */
463         freePartialList();
464         freeAllocation(datAuthor);
465         freeAllocation(datFileName);
466         freeAllocation(datFilePath);
467         freeAllocation(extension);
468         freeAllocation(resFile);
469
470         return 0;
471 }
472
473 #endif
474
475 /***************************************************************\
476 |              Main Library start dummy function                |
477 \***************************************************************/
478
479 #ifdef SO
480 /* When compiling in Unix SO libraries */
481 void start() {}
482 #endif
483
484
485