author | ecalot
<ecalot> 2003-12-08 13:26:20 UTC |
committer | ecalot
<ecalot> 2003-12-08 13:26:20 UTC |
parent | 74a019c053f59d7a7b463bebaca48add59363c37 |
PR/src/console/main.c | +265 | -107 |
PR/src/lib/actions/classify.c | +1 | -1 |
PR/src/lib/actions/export.c | +19 | -12 |
PR/src/lib/actions/import.c | +71 | -54 |
PR/src/lib/layers/disk.c | +29 | -11 |
PR/src/lib/pr.c | +265 | -107 |
PR/src/lib/xml/search.c | +21 | -0 |
PR/src/xml.c | +5 | -1 |
diff --git a/PR/src/console/main.c b/PR/src/console/main.c index b5eb371..0bce2ad 100644 --- a/PR/src/console/main.c +++ b/PR/src/console/main.c @@ -39,11 +39,15 @@ pr.c: Main source file for Princed Resources MID Sound format development Christian Lundheim + Resources.xml edition + Steven Fayers + Note: DO NOT remove this copyright notice */ //Headers +#include <stdio.h> #include <string.h> #include "pr.h" @@ -54,30 +58,59 @@ pr.c: Main source file for Princed Resources #include "compile.h" #include "tasks.h" -#include "bmp.h" -#include "memory.h" -#include "disk.h" +#include "memory.h" /* getMemory, free */ +#include "disk.h" /* getFileNameFromPath */ + +#ifndef DLL + #ifdef UNIX + #include <stduni.h> + #else + #include "getopt.h" + #endif +#endif + //functions -int prExportDat(char* vDatFile, char* vDirName, char* vResFile) { - return prExportDatOpt(vDatFile,vDirName,vResFile,3); +int prExportDat(const char* vDatFile, const char* vDirName, const char* vResFile) { + return prExportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL,""); } -int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { +int prExportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName,const char* datAuthor, const char* backupExtension) { /* + Arguments: + char* vDatFile - full Path to the dat file; + if file use it, if dir, perform it for + all files + char* vDirName - full Path to the extracting folder + (doesn't need to exist) + char* vResFile - full Path to the resources XML file + (resources.xml by default) + No NULL + char opt - program options, see below + char * vDatFileName - name of the file to be extracted + NULL means predict it from vDatFile + const char* datAuthor - Author's name when extracting PLV's, + NULL is default + const char* backupExtension + - If backup_flag is set, the string to attach + to the backup files + Options: - 0 - none - 1 - extract - 2 - update resources (rebuild resources list) - 3 - 1&2 - 4 - use raw file if extraction - 5 - 1&4 - 8 - Don't save + unknown_flag - generate the unknown file without performing + any extraction + raw_flag - uses raw format + verbose_flag - explain what is being done +x recursive_flag - searches for all dat files (only if vDatFile + is not a dat file and vDatFileName is NULL) +x force_flag - default option, you cannot disable it, + so please make a backup of your files +x backup_flag - backup your files + Return values: 00 Ok - -1 Error accesing the file DAT + -1 Error accessing the file DAT -2 Memory error in extraction -3 Invalid DAT file -4 XML Parse error @@ -85,24 +118,55 @@ int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { -6 XML Attribute not recognized -7 XML File not found */ + + //Declare variables tResource* r[MAX_RES_COUNT]; int a; + const char defaultXmlFile[]=RES_XML_RESOURC_XML; - a=parseFile (vResFile,vDatFile,r); - if (a<0) return a-3; - a=extract(vDatFile, vDirName,r,opt); - return a; + //Set default values + if (vResFile==NULL) vResFile=defaultXmlFile; + if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile); + + //Parse XML and extract the file + a=parseFile (vResFile,vDatFileName,r); + if (a<0) return a-3; //parsing errors + a=extract(vDatFile, vDirName,r,opt,vDatFileName); + printf("-3 es error: %d\n",a); + return a; //extracting errors/no errors } -int prImportDat(char* vDatFile, char* vDirName, char* vResFile) { - return prImportDatOpt(vDatFile,vDirName,vResFile,1); +int prImportDat(const char* vDatFile, const char* vDirName, const char* vResFile) { + return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,""); } -int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { +int prImportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName, const char* backupExtension) { /* + Arguments: + char* vDatFile - full Path to the dat file; + if file use it, if dir, perform it for + all files + char* vDirName - full Path to the extracting folder + (doesn't need to exist) + char* vResFile - full Path to the resources XML file + (resources.xml by default) + No NULL + char opt - program options, see below + char * vDatFileName - name of the file to be extracted + NULL means predict it from vDatFile + const char* backupExtension + - If backup_flag is set, the string to attach + to the backup files + Options: - 0 - use raw files - 1 - read data type + raw_flag - uses raw format + verbose_flag - explain what is being done +x recursive_flag - searches for all dat files (only if vDatFile + is not a dat file and vDatFileName is NULL) +x force_flag - default option, you cannot disable it, + so please make a backup of your files +x backup_flag - backup your files + Return values: -1 DAT File couldn't be open for writing @@ -113,118 +177,212 @@ int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { 00 File succesfully compiled positive number: number of missing files */ - tResource* r[MAX_RES_COUNT]; + + //Declare variables + tResource* r[MAX_RES_COUNT]; int a; - a=parseFile (vResFile,vDatFile,r); + const char defaultXmlFile[]=RES_XML_RESOURC_XML; + + //Set default values + if (vResFile==NULL) vResFile=defaultXmlFile; + if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile); + + //Parser XML and compile files + a=parseFile (vResFile,vDatFileName,r); if (a<0) return a-1; - a=compile (vDatFile, vDirName,r,opt); + a=compile (vDatFile, vDirName,r,opt,vDatFileName); return a; } + +/******************************************************* + M A I N P R O G R A M + *******************************************************/ + + + //Main program #ifndef DLL void syntax() { - printf(PR_TEXT_SYNTAX); + printf(PARSING_HELP); } -int main(int argc, char* argv[]) { +int prMain(int option, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor) { //declare variables - char dir[260]="."; int returnValue=1; - int option; - int i; -#ifdef UNIX - if (argc==2) { //CGI support + //Do CGI tasks + if (option&cgi_flag) { + option&=(~classify_flag); printf(PR_CGI_TEXT1); - printf(PR_CGI_TEXT2,prVerifyDatType(argv[1])); - return 1; + if (option==cgi_flag) { + printf(PR_CGI_TEXT2,prVerifyDatType(datfile)); + return 1; + } else { + option=help_flag; + } } -#endif printf(PR_ABOUT); - //Verify syntax - if ((argc<3)||(argc>4)||(argv[2][0])!='-') { + //If bad syntax or help screen requested + if (option&help_flag) { syntax(); return -1; } - if (argc==4 ) { - if (strlen(argv[3])<(260-1)) sprintf(dir,argv[3]); + + if ((datfile==NULL)||option&version_flag) { //TODO use the recursive option and/or generic datfile + return -1; } //do selected tasks - switch (argv[2][1]) { - case 'e': - case 'x': {// file.dat --> extracted files + resource.xml - char array[8][29]={ - "Ok", - "Error accesing the file DAT", /* DAT or extracted */ - "Memory error in extraction", - "Invalid DAT file", - "XML Parse error", - "Memory error in parsing", - "XML Attribute not recognized", - "XML File not found"}; - option=1; - for (i=2;argv[2][i];i++) { - switch (argv[2][i]) { - case 'n':option&=0xFE;break; - case 'r':option|=0x04;break; - default:printf(PR_TEXT_SKIPING,argv[2][i]);break; - } - } - printf("Extracting '%s' to '%s' with %d\r\n",argv[1],dir,option); - returnValue=prExportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option); + if (option&export_flag) { + char* array[]={ + "Ok", + "Error accessing the file DAT", /* DAT or extracted */ + "Memory error in extraction", + "Invalid DAT file", + "XML Parse error", + "Memory error in parsing", + "XML Attribute not recognized", + "XML File not found"}; + printf("Extracting '%s' to '%s' with %04x\r\n",datfile,dirName,option); + returnValue=prExportDatOpt(datfile,dirName,resFile,option,NULL,datAuthor,extension); + printf(PR_TEXT_RESULT,array[-returnValue],returnValue); + } else if (option&classify_flag) { + char* array[]={ + "Memory error", + "File not found or no access error", + "Not a valid POP1 DAT file", + "Levels file", + "Graphic file with an image in the first valid entry (not common)", + "Waves/Digital sound file", + "Midis file", + "Valid DAT file with Undefined content", + "Graphic file with a palette in the first valid entry (common)", + "PC Speaker dat file", + "\0","\0","\0", + "Pop2 dat files"}; + printf("Classifing '%s'\r\n",datfile); + returnValue=prVerifyDatType(datfile); + printf(PR_TEXT_RESULT,array[2+returnValue],returnValue); + } else if (option&import_flag) { + char* array[]={ + "File succesfully compiled", + "DAT File couldn't be open for writing", + "XML Parse error", + "No memory", + "XML Attribute not recognized", + "XML File not found"}; + printf("Compiling '%s' from '%s' with %04x\r\n",datfile,dirName,option); + returnValue=prImportDatOpt(datfile,dirName,resFile,option,NULL,extension); + if (returnValue<=0) { printf(PR_TEXT_RESULT,array[-returnValue],returnValue); - } break; - case 'd': {// get type of file.dat - char array[14][65]={ - "Memory error", - "File not found or no access error", - "Not a valid POP1 DAT file", - "Levels file", - "Graphic file with an image in the first valid entry (not common)", - "Waves/Digital sound file", - "Midis file", - "Valid DAT file with Undefined content", - "Graphic file with a palette in the first valid entry (common)", - "PC Speaker dat file", - "\0","\0","\0", - "Pop2 dat files"}; - printf("Classifing '%s'\r\n",argv[1]); - returnValue=prVerifyDatType(argv[1]); - printf(PR_TEXT_RESULT,array[2+returnValue],returnValue); - } break; - case 'c': { // extracted files + resource.xml --> files.dat - char array[6][39]={ - "File succesfully compiled", - "DAT File couldn't be open for writing", - "XML Parse error", - "No memory", - "XML Attribute not recognized", - "XML File not found"}; - option=1; - for (i=2;argv[2][i];i++) { - switch (argv[2][i]) { - case 'r':option&=0xFE;break; - default:printf(PR_TEXT_SKIPING,argv[2][i]);break; - } - } - printf("Compiling '%s' from '%s' with %d\r\n",argv[1],dir,option); - returnValue=prImportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option); - if (returnValue>=0) { - printf(PR_TEXT_RESULT,array[-returnValue],returnValue); - } else { - printf(PR_TEXT_RESULT_ERR,returnValue); - } - } break; - default: - syntax(); - return -1; + } else { + printf(PR_TEXT_RESULT_ERR,returnValue); + } + } else { + syntax(); + return -1; } return returnValue; } +int main (int argc, char **argv) { + //declare variables + char datFileName[MAX_FILENAME_SIZE]; //TODO add + char dirName[MAX_FILENAME_SIZE]="."; + char extension[MAX_EXTENSION_SIZE]=DEFAULT_BACKUP_EXTENSION; + char resFile[MAX_FILENAME_SIZE]=RES_XML_RESOURC_XML; + char* datFilePath; + char* datAuthor=NULL; + int c; + int flag=0; + + //Parse options + while (1) { + + static struct option long_options[] = PARSING_OPTIONS; + + /* getopt_long stores the option index here. */ + int option_index = 0; + c = getopt_long (argc, argv, PARSING_CHARS,long_options,&option_index); + + /* Detect the end of the options. */ + if (c == -1) break; + + switch (c) { + case 'c': + flag|=import_flag; + if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE); + break; + case 'd': + flag|=force_flag; + break; + case 'x': + case 'e': + flag|=export_flag; + if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE); + break; + case 'b': + flag|=backup_flag; + if (optarg) strncpy(extension,optarg,MAX_FILENAME_SIZE); + break; + case 'f': + flag|=force_flag; + break; + case 'g': + flag|=cgi_flag; + break; + case 'm': + strncpy(resFile,optarg,MAX_FILENAME_SIZE); + break; + case 'r': + flag|=raw_flag; + break; + case 'R': + flag|=force_flag; + break; + case 't': { + int size; + size=strlen(optarg)+1; + datAuthor=getMemory(size); + memcpy(datAuthor,optarg,size); + } break; + case 'v': + flag|=verbose_flag; + break; + case 1: + flag|=version_flag; + break; + case 2: + flag|=unknown_flag; + break; + default: + flag|=help_flag; + } + } + + if (optind < argc) { + datFilePath=argv[optind]; + } else { + datFilePath=NULL; + } + + if (!flag) flag=help_flag; + + //Run main program + prMain(flag,extension,dirName,resFile,datFilePath,datFileName,datAuthor); + + //Free memory and exit + if (datAuthor!=NULL) free(datAuthor); + return 0; +} + +#endif + +#ifdef SO +//When compiling in Unix SO libraries +void start() {} #endif diff --git a/PR/src/lib/actions/classify.c b/PR/src/lib/actions/classify.c index b4acd7b..2782d0f 100644 --- a/PR/src/lib/actions/classify.c +++ b/PR/src/lib/actions/classify.c @@ -40,7 +40,7 @@ tasks.c: Princed Resources : Other DAT file handling tasks | Get the type of a DAT file | \***************************************************************/ -int prVerifyDatType(char* vFiledat) { +int prVerifyDatType(const char* vFiledat) { //Variables FILE* fp; diff --git a/PR/src/lib/actions/export.c b/PR/src/lib/actions/export.c index aee1e56..de67bed 100644 --- a/PR/src/lib/actions/export.c +++ b/PR/src/lib/actions/export.c @@ -43,6 +43,7 @@ extract.c: Princed Resources : DAT Extractor #include "bmp.h" #include "wav.h" #include "pal.h" +#include "plv.h" #include "mid.h" /***************************************************************\ @@ -66,7 +67,7 @@ extract.c: Princed Resources : DAT Extractor 5 - 1&4 */ -int extract(char* vFiledat,char* vDirExt, tResource* r[], char task) { +int extract(const char* vFiledat,const char* vDirExt, tResource* r[], int task, const char* vDatFileName) { //Variables char vFileext[260]; @@ -136,33 +137,36 @@ int extract(char* vFiledat,char* vDirExt, tResource* r[], char task) { ok=ok&&fread(data,size,1,fp); if (!ok) return -3; - //For the moment rebuilt option will be comented -// task|=2; - //set resource information on this index entry if (r[id]==NULL) { r[id]=(tResource*)malloc(sizeof(tResource)); if (r[id]==NULL) return -2; //no memory r[id]->path=NULL; r[id]->palAux=NULL; + r[id]->desc=NULL; + r[id]->title=NULL; r[id]->palette=0; - (*(r[id])).size=(unsigned short int)size; - (*(r[id])).offset=(unsigned short)offset; - (*(r[id])).type=verifyHeader(data,(unsigned short int)size); - } else { + r[id]->number=0; + r[id]->size=(unsigned short int)size; + r[id]->offset=(unsigned short)offset; + r[id]->type=verifyHeader(data,(unsigned short int)size); + } else { //If resource type is invalid or 0, the type will be decided by PR if (!(r[id]->type)) r[id]->type=verifyHeader(data,(unsigned short int)size); } - if (task&1) { //If "extract to file" is set + if (!(task&unknown_flag)) { //If unknown flag is set do nothing but generate the unknown.xml file //select type - if (task&4) (*(r[id])).type=0; //If "extract as raw" is set type is 0 + if (task&raw_flag) (*(r[id])).type=0; //If "extract as raw" is set type is 0 //save file getFileName(vFileext,vDirExt,r[id],id,vFiledat); + if (task&verbose_flag) printf("Extracting '%s'...\n",getFileNameFromPath(vFileext)); - switch ((*(r[id])).type) { + switch (r[id]->type) { case 1: + ok=ok&&mFormatExtractPlv(data,vFileext,size,r[id]->number,vDatFileName,r[id]->title,r[id]->desc); + break; case 5: case 0: //Raw files ok=ok&&writeData(data,1,vFileext,size); //Ignore checksum @@ -209,12 +213,15 @@ int extract(char* vFiledat,char* vDirExt, tResource* r[], char task) { } fclose(fp); - //Free allocated palettes + //Free allocated palettes and descriptions for (id=0;id<MAX_RES_COUNT;id++) { if (r[id]!=NULL) { if (r[id]->palAux!=NULL) { free (r[id]->palAux); } + if (r[id]->desc!=NULL) { + free (r[id]->palAux); + } } } diff --git a/PR/src/lib/actions/import.c b/PR/src/lib/actions/import.c index ce1e860..fd4fff6 100644 --- a/PR/src/lib/actions/import.c +++ b/PR/src/lib/actions/import.c @@ -42,6 +42,7 @@ compile.c: Princed Resources : DAT Compiler #include "mid.h" #include "wav.h" #include "pal.h" +#include "plv.h" #include "disk.h" #include "pr.h" @@ -49,10 +50,13 @@ compile.c: Princed Resources : DAT Compiler | Dat compiling primitives | \***************************************************************/ -char mBeginDatFile(FILE* *fp,char* vFile) { - //opens a file and reserves space for the headers - *fp=fopen(vFile,"wb"); - if (*fp!=NULL) { +char mBeginDatFile(FILE* *fp,const char* vFile) { + /* + Opens safely a dat file for writing mode and + reserves space for the headers + */ + + if (writeOpen(vFile,fp)) { fseek(*fp,6,SEEK_SET); return 1; } else { @@ -61,61 +65,69 @@ char mBeginDatFile(FILE* *fp,char* vFile) { } void mAddFileToDatFile(FILE* fp, char* data, int size) { - //calculates the checksum of a file - unsigned char checksum=0; - int k; - for (k=0;k<size;k++) checksum+=data[k]; + /* + Adds a data resource to a dat file keeping + abstratly the checksum verifications + */ + + //Declare variables + int k = size; + unsigned char checksum = 0; + unsigned char* data2 = data; + + //calculates the checksum + while (k--) checksum+=*(data2++); checksum=~checksum; + //writes the checksum and the data content fwrite(&checksum,1,1,fp); fwrite(data,size,1,fp); } -void mSetEndFile(FILE* fp,int sizeOfIndex) { - //sets the headers - short int size1,zero,size2; - fseek(fp,0,SEEK_END); - size1=ftell(fp)-(size2=sizeOfIndex); - zero=0; - fseek(fp,0,SEEK_SET); - fwrite(&size1,2,1,fp); - fwrite(&zero,2,1,fp); - fwrite(&size2,2,1,fp); - fclose(fp); -} - -int mCreateIndexInDatFile(FILE* fp, tResource* r[]) { - //Add extra text at the end of the file - unsigned short int i=0; - unsigned short int junk=0; - unsigned short int tot=0; - int k=2; - int pos=ftell(fp); +void mSetEndFile(FILE* fp, tResource* r[]) { + /* + Closes a dat file filling the index and other structures + */ + unsigned short int i=1; + unsigned short int totalItems=0; + unsigned short int size2=2; + unsigned long int size1=ftell(fp); - fwrite(&tot,2,1,fp); - for (;i!=MAX_RES_COUNT;i++) { //TODO: add define MAX_RES_COUNT + //Write index + fwrite(&totalItems,2,1,fp); //Junk total items count to reserve 2 bytes + for (;i!=MAX_RES_COUNT;i++) { if (r[i]!=NULL) { - //the file is in the archive, so I'll add it to the index - k+=8; - tot++; - fwrite(&i,2,1,fp); - fwrite(&((*r[i]).offset),2,1,fp); - fwrite(&junk,2,1,fp); - fwrite(&((*r[i]).size),2,1,fp); + //the file is in the archive, so I'll add it to the index + size2+=8; + totalItems++; + fwrite(&i,2,1,fp); + fwrite(&((*r[i]).offset),4,1,fp); + fwrite(&((*r[i]).size),2,1,fp); } } - fseek(fp,pos,SEEK_SET); - fwrite(&tot,2,1,fp); - return k; + fseek(fp,size1,SEEK_SET); + fwrite(&totalItems,2,1,fp); //Definitive total items count + + //Write first 6 bytes header + fseek(fp,0,SEEK_SET); + fwrite(&size1,4,1,fp); + fwrite(&size2,2,1,fp); + + //Closes the file and flushes the buffer + fclose(fp); } //Format detection function (private function, not in header file) char mAddCompiledFileToDatFile(FILE* fp,unsigned char** data, tResource *res) { - switch ((*res).type) { + //return 1 if ok, 0 if error + switch (res->type) { + case 1: //compile levels + return mFormatCompilePlv(*data,fp,res); case 2: //compile bitmap return mFormatCompileBmp(*data,fp,res); case 3: //compile wave return mFormatCompileWav(*data,fp,res); + case 7: //compile pcs case 4: //compile midi return mFormatCompileMid(*data,fp,res); case 6: //compile palette @@ -123,7 +135,6 @@ char mAddCompiledFileToDatFile(FILE* fp,unsigned char** data, tResource *res) { if (!mImportPalette(data,&((*res).size))) { return 0; } - case 1: case 5: default: mAddFileToDatFile(fp,*data,(*res).size); @@ -136,7 +147,7 @@ char mAddCompiledFileToDatFile(FILE* fp,unsigned char** data, tResource *res) { | M A I N F U N C T I O N | \***************************************************************/ -int compile(char* vFiledat, char* vDirExt, tResource* r[], char opt) { +int compile(const char* vFiledat, const char* vDirExt, tResource* r[], int opt, const char* vDatFileName) { /* Return values: -1 File couldn't be open for writing @@ -148,7 +159,7 @@ int compile(char* vFiledat, char* vDirExt, tResource* r[], char opt) { char vFileext[200]; int ok=0; unsigned char* data; - unsigned short int i=0; + unsigned short int i=1; if (!mBeginDatFile(&fp,vFiledat)) { return -1; //File couldn't be open @@ -158,19 +169,25 @@ int compile(char* vFiledat, char* vDirExt, tResource* r[], char opt) { for (;i!=MAX_RES_COUNT;i++) { if (r[i]!=NULL) { - getFileName(vFileext,vDirExt,r[i],i,vFiledat); - //the file is in the archive, so I'll add it to the main dat body - if ((*r[i]).size=mLoadFileArray(vFileext,&data)) { - (*r[i]).offset=(unsigned short)ftell(fp); - if (!mAddCompiledFileToDatFile(fp,&data,r[i])) { - ok++; - } - free(data); - } else { + if (opt&raw_flag) r[i]->type=0; //compile from raw + getFileName(vFileext,vDirExt,r[i],i,vDatFileName); + //the file is in the archive, so I'll add it to the main dat body + if (r[i]->size=mLoadFileArray(vFileext,&data)) { + r[i]->offset=(unsigned short)ftell(fp); + if (!mAddCompiledFileToDatFile(fp,&data,r[i])) { + if (opt&verbose_flag) printf("'%s' has errors, skipped\n",getFileNameFromPath(vFileext)); ok++; + } else { + if (opt&verbose_flag) printf("'%s' succesfully compiled\n",getFileNameFromPath(vFileext)); } + free(data); + } else { + if (opt&verbose_flag) printf("'%s' not open, skipped\n",getFileNameFromPath(vFileext)); + ok++; + } } } - mSetEndFile(fp,mCreateIndexInDatFile(fp,r)); + mSetEndFile(fp,r); + if (opt&verbose_flag) printf("Compilation done\n"); return ok; } diff --git a/PR/src/lib/layers/disk.c b/PR/src/lib/layers/disk.c index 31da622..b0a25a8 100644 --- a/PR/src/lib/layers/disk.c +++ b/PR/src/lib/layers/disk.c @@ -55,21 +55,23 @@ disk.c: Princed Resources : Disk Access & File handling functions \***************************************************************/ //Repair folders -void repairFolders(char* a) { +const char *repairFolders(const char* a) { int i,k; + static char result[260]; - for (i=0,k=0;a[i];) { + for (i=0,k=0;a[i]&&(k<260);) { if (isDirSep(a,i)) { - a[k]=DIR_SEPARATOR; + result[k]=DIR_SEPARATOR; i++; while (isDirSep(a,i)) i++; } else { - a[k]=a[i]; + result[k]=a[i]; i++; } k++; } - a[k]=0; + result[k]=0; + return result; } @@ -102,7 +104,7 @@ int makebase(const char* p) { return a; } -char writeOpen(char* vFileext, FILE* *fp) { +char writeOpen(const char* vFileext, FILE* *fp) { /* Opens vFileext for write access if the path does't exist it is created @@ -115,12 +117,13 @@ char writeOpen(char* vFileext, FILE* *fp) { 0 if error 1 if ok */ + const char* file; //Create base dir and save file - repairFolders(vFileext); - if (makebase(vFileext)) return 0; + file=repairFolders(vFileext); + makebase(file); - return ((*fp=fopen(vFileext,"wb"))!=NULL); + return ((*fp=fopen(file,"wb"))!=NULL); } @@ -166,7 +169,7 @@ int mLoadFileArray(const char* vFile,unsigned char** array) { int aux; //Open the file - if ((fp=fopen(vFile,"rb"))==NULL) { + if ((fp=fopen(repairFolders(vFile),"rb"))==NULL) { return 0; } else { //get file size @@ -199,7 +202,7 @@ char mSaveRaw(const char* vFile,const unsigned char* output, int size) { FILE * pFile; if (!size) return 0; - if ((pFile=fopen(vFile,"wb"))==NULL) return 0; + if (!writeOpen(vFile,&pFile)) return 0; fwrite (output, 1, size, pFile); fclose (pFile); @@ -238,5 +241,20 @@ char mDiskVealidateFileHeader(unsigned char* text, int size, FILE* fp) { return (i==size); //0 if the compare for was stopped before end reached } +const char* getFileNameFromPath(const char* path) { + /* + If you give a path you get the filename, + if you give a filename, you get the same filename + */ + int size; + size=strlen(path); + while (size) { + if (isDirSep(path,size)) { + return path+size+1; + } + size--; + } + return path; +} diff --git a/PR/src/lib/pr.c b/PR/src/lib/pr.c index b5eb371..0bce2ad 100644 --- a/PR/src/lib/pr.c +++ b/PR/src/lib/pr.c @@ -39,11 +39,15 @@ pr.c: Main source file for Princed Resources MID Sound format development Christian Lundheim + Resources.xml edition + Steven Fayers + Note: DO NOT remove this copyright notice */ //Headers +#include <stdio.h> #include <string.h> #include "pr.h" @@ -54,30 +58,59 @@ pr.c: Main source file for Princed Resources #include "compile.h" #include "tasks.h" -#include "bmp.h" -#include "memory.h" -#include "disk.h" +#include "memory.h" /* getMemory, free */ +#include "disk.h" /* getFileNameFromPath */ + +#ifndef DLL + #ifdef UNIX + #include <stduni.h> + #else + #include "getopt.h" + #endif +#endif + //functions -int prExportDat(char* vDatFile, char* vDirName, char* vResFile) { - return prExportDatOpt(vDatFile,vDirName,vResFile,3); +int prExportDat(const char* vDatFile, const char* vDirName, const char* vResFile) { + return prExportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL,""); } -int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { +int prExportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName,const char* datAuthor, const char* backupExtension) { /* + Arguments: + char* vDatFile - full Path to the dat file; + if file use it, if dir, perform it for + all files + char* vDirName - full Path to the extracting folder + (doesn't need to exist) + char* vResFile - full Path to the resources XML file + (resources.xml by default) + No NULL + char opt - program options, see below + char * vDatFileName - name of the file to be extracted + NULL means predict it from vDatFile + const char* datAuthor - Author's name when extracting PLV's, + NULL is default + const char* backupExtension + - If backup_flag is set, the string to attach + to the backup files + Options: - 0 - none - 1 - extract - 2 - update resources (rebuild resources list) - 3 - 1&2 - 4 - use raw file if extraction - 5 - 1&4 - 8 - Don't save + unknown_flag - generate the unknown file without performing + any extraction + raw_flag - uses raw format + verbose_flag - explain what is being done +x recursive_flag - searches for all dat files (only if vDatFile + is not a dat file and vDatFileName is NULL) +x force_flag - default option, you cannot disable it, + so please make a backup of your files +x backup_flag - backup your files + Return values: 00 Ok - -1 Error accesing the file DAT + -1 Error accessing the file DAT -2 Memory error in extraction -3 Invalid DAT file -4 XML Parse error @@ -85,24 +118,55 @@ int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { -6 XML Attribute not recognized -7 XML File not found */ + + //Declare variables tResource* r[MAX_RES_COUNT]; int a; + const char defaultXmlFile[]=RES_XML_RESOURC_XML; - a=parseFile (vResFile,vDatFile,r); - if (a<0) return a-3; - a=extract(vDatFile, vDirName,r,opt); - return a; + //Set default values + if (vResFile==NULL) vResFile=defaultXmlFile; + if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile); + + //Parse XML and extract the file + a=parseFile (vResFile,vDatFileName,r); + if (a<0) return a-3; //parsing errors + a=extract(vDatFile, vDirName,r,opt,vDatFileName); + printf("-3 es error: %d\n",a); + return a; //extracting errors/no errors } -int prImportDat(char* vDatFile, char* vDirName, char* vResFile) { - return prImportDatOpt(vDatFile,vDirName,vResFile,1); +int prImportDat(const char* vDatFile, const char* vDirName, const char* vResFile) { + return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,""); } -int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { +int prImportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName, const char* backupExtension) { /* + Arguments: + char* vDatFile - full Path to the dat file; + if file use it, if dir, perform it for + all files + char* vDirName - full Path to the extracting folder + (doesn't need to exist) + char* vResFile - full Path to the resources XML file + (resources.xml by default) + No NULL + char opt - program options, see below + char * vDatFileName - name of the file to be extracted + NULL means predict it from vDatFile + const char* backupExtension + - If backup_flag is set, the string to attach + to the backup files + Options: - 0 - use raw files - 1 - read data type + raw_flag - uses raw format + verbose_flag - explain what is being done +x recursive_flag - searches for all dat files (only if vDatFile + is not a dat file and vDatFileName is NULL) +x force_flag - default option, you cannot disable it, + so please make a backup of your files +x backup_flag - backup your files + Return values: -1 DAT File couldn't be open for writing @@ -113,118 +177,212 @@ int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) { 00 File succesfully compiled positive number: number of missing files */ - tResource* r[MAX_RES_COUNT]; + + //Declare variables + tResource* r[MAX_RES_COUNT]; int a; - a=parseFile (vResFile,vDatFile,r); + const char defaultXmlFile[]=RES_XML_RESOURC_XML; + + //Set default values + if (vResFile==NULL) vResFile=defaultXmlFile; + if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile); + + //Parser XML and compile files + a=parseFile (vResFile,vDatFileName,r); if (a<0) return a-1; - a=compile (vDatFile, vDirName,r,opt); + a=compile (vDatFile, vDirName,r,opt,vDatFileName); return a; } + +/******************************************************* + M A I N P R O G R A M + *******************************************************/ + + + //Main program #ifndef DLL void syntax() { - printf(PR_TEXT_SYNTAX); + printf(PARSING_HELP); } -int main(int argc, char* argv[]) { +int prMain(int option, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor) { //declare variables - char dir[260]="."; int returnValue=1; - int option; - int i; -#ifdef UNIX - if (argc==2) { //CGI support + //Do CGI tasks + if (option&cgi_flag) { + option&=(~classify_flag); printf(PR_CGI_TEXT1); - printf(PR_CGI_TEXT2,prVerifyDatType(argv[1])); - return 1; + if (option==cgi_flag) { + printf(PR_CGI_TEXT2,prVerifyDatType(datfile)); + return 1; + } else { + option=help_flag; + } } -#endif printf(PR_ABOUT); - //Verify syntax - if ((argc<3)||(argc>4)||(argv[2][0])!='-') { + //If bad syntax or help screen requested + if (option&help_flag) { syntax(); return -1; } - if (argc==4 ) { - if (strlen(argv[3])<(260-1)) sprintf(dir,argv[3]); + + if ((datfile==NULL)||option&version_flag) { //TODO use the recursive option and/or generic datfile + return -1; } //do selected tasks - switch (argv[2][1]) { - case 'e': - case 'x': {// file.dat --> extracted files + resource.xml - char array[8][29]={ - "Ok", - "Error accesing the file DAT", /* DAT or extracted */ - "Memory error in extraction", - "Invalid DAT file", - "XML Parse error", - "Memory error in parsing", - "XML Attribute not recognized", - "XML File not found"}; - option=1; - for (i=2;argv[2][i];i++) { - switch (argv[2][i]) { - case 'n':option&=0xFE;break; - case 'r':option|=0x04;break; - default:printf(PR_TEXT_SKIPING,argv[2][i]);break; - } - } - printf("Extracting '%s' to '%s' with %d\r\n",argv[1],dir,option); - returnValue=prExportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option); + if (option&export_flag) { + char* array[]={ + "Ok", + "Error accessing the file DAT", /* DAT or extracted */ + "Memory error in extraction", + "Invalid DAT file", + "XML Parse error", + "Memory error in parsing", + "XML Attribute not recognized", + "XML File not found"}; + printf("Extracting '%s' to '%s' with %04x\r\n",datfile,dirName,option); + returnValue=prExportDatOpt(datfile,dirName,resFile,option,NULL,datAuthor,extension); + printf(PR_TEXT_RESULT,array[-returnValue],returnValue); + } else if (option&classify_flag) { + char* array[]={ + "Memory error", + "File not found or no access error", + "Not a valid POP1 DAT file", + "Levels file", + "Graphic file with an image in the first valid entry (not common)", + "Waves/Digital sound file", + "Midis file", + "Valid DAT file with Undefined content", + "Graphic file with a palette in the first valid entry (common)", + "PC Speaker dat file", + "\0","\0","\0", + "Pop2 dat files"}; + printf("Classifing '%s'\r\n",datfile); + returnValue=prVerifyDatType(datfile); + printf(PR_TEXT_RESULT,array[2+returnValue],returnValue); + } else if (option&import_flag) { + char* array[]={ + "File succesfully compiled", + "DAT File couldn't be open for writing", + "XML Parse error", + "No memory", + "XML Attribute not recognized", + "XML File not found"}; + printf("Compiling '%s' from '%s' with %04x\r\n",datfile,dirName,option); + returnValue=prImportDatOpt(datfile,dirName,resFile,option,NULL,extension); + if (returnValue<=0) { printf(PR_TEXT_RESULT,array[-returnValue],returnValue); - } break; - case 'd': {// get type of file.dat - char array[14][65]={ - "Memory error", - "File not found or no access error", - "Not a valid POP1 DAT file", - "Levels file", - "Graphic file with an image in the first valid entry (not common)", - "Waves/Digital sound file", - "Midis file", - "Valid DAT file with Undefined content", - "Graphic file with a palette in the first valid entry (common)", - "PC Speaker dat file", - "\0","\0","\0", - "Pop2 dat files"}; - printf("Classifing '%s'\r\n",argv[1]); - returnValue=prVerifyDatType(argv[1]); - printf(PR_TEXT_RESULT,array[2+returnValue],returnValue); - } break; - case 'c': { // extracted files + resource.xml --> files.dat - char array[6][39]={ - "File succesfully compiled", - "DAT File couldn't be open for writing", - "XML Parse error", - "No memory", - "XML Attribute not recognized", - "XML File not found"}; - option=1; - for (i=2;argv[2][i];i++) { - switch (argv[2][i]) { - case 'r':option&=0xFE;break; - default:printf(PR_TEXT_SKIPING,argv[2][i]);break; - } - } - printf("Compiling '%s' from '%s' with %d\r\n",argv[1],dir,option); - returnValue=prImportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option); - if (returnValue>=0) { - printf(PR_TEXT_RESULT,array[-returnValue],returnValue); - } else { - printf(PR_TEXT_RESULT_ERR,returnValue); - } - } break; - default: - syntax(); - return -1; + } else { + printf(PR_TEXT_RESULT_ERR,returnValue); + } + } else { + syntax(); + return -1; } return returnValue; } +int main (int argc, char **argv) { + //declare variables + char datFileName[MAX_FILENAME_SIZE]; //TODO add + char dirName[MAX_FILENAME_SIZE]="."; + char extension[MAX_EXTENSION_SIZE]=DEFAULT_BACKUP_EXTENSION; + char resFile[MAX_FILENAME_SIZE]=RES_XML_RESOURC_XML; + char* datFilePath; + char* datAuthor=NULL; + int c; + int flag=0; + + //Parse options + while (1) { + + static struct option long_options[] = PARSING_OPTIONS; + + /* getopt_long stores the option index here. */ + int option_index = 0; + c = getopt_long (argc, argv, PARSING_CHARS,long_options,&option_index); + + /* Detect the end of the options. */ + if (c == -1) break; + + switch (c) { + case 'c': + flag|=import_flag; + if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE); + break; + case 'd': + flag|=force_flag; + break; + case 'x': + case 'e': + flag|=export_flag; + if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE); + break; + case 'b': + flag|=backup_flag; + if (optarg) strncpy(extension,optarg,MAX_FILENAME_SIZE); + break; + case 'f': + flag|=force_flag; + break; + case 'g': + flag|=cgi_flag; + break; + case 'm': + strncpy(resFile,optarg,MAX_FILENAME_SIZE); + break; + case 'r': + flag|=raw_flag; + break; + case 'R': + flag|=force_flag; + break; + case 't': { + int size; + size=strlen(optarg)+1; + datAuthor=getMemory(size); + memcpy(datAuthor,optarg,size); + } break; + case 'v': + flag|=verbose_flag; + break; + case 1: + flag|=version_flag; + break; + case 2: + flag|=unknown_flag; + break; + default: + flag|=help_flag; + } + } + + if (optind < argc) { + datFilePath=argv[optind]; + } else { + datFilePath=NULL; + } + + if (!flag) flag=help_flag; + + //Run main program + prMain(flag,extension,dirName,resFile,datFilePath,datFileName,datAuthor); + + //Free memory and exit + if (datAuthor!=NULL) free(datAuthor); + return 0; +} + +#endif + +#ifdef SO +//When compiling in Unix SO libraries +void start() {} #endif diff --git a/PR/src/lib/xml/search.c b/PR/src/lib/xml/search.c index b3aa2b5..90f8203 100644 --- a/PR/src/lib/xml/search.c +++ b/PR/src/lib/xml/search.c @@ -82,6 +82,7 @@ void workTag(const tTag* t, tResource* r[]) { int i; id=(unsigned short)ptoi(t->value); + if (!id) return; //If there was not id or id contained wrong values, skip //Process tag and copy values to resource //Create Resource @@ -97,6 +98,26 @@ void workTag(const tTag* t, tResource* r[]) { } if (i==8) r[id]->type=(char)atoi(t->itemtype); //If error it returns 0 and the verifyHeader will try to detect the type r[id]->palette=(unsigned short)ptoi(t->palette); //Transforms the char* palette into a short ID value, if 0 or error no palette is needed + r[id]->number=(unsigned char)ptoi(t->number); //Transforms the char* levelnumer/number attribute into a char value, if error, demo level is used + + //Title and description (only supported in level plv format + if (t->desc!=NULL) { + size=strlen(t->desc)+1; + r[id]->desc=(char*)malloc(size); + if (r[id]->desc==NULL) return; + memcpy(r[id]->desc,t->desc,size); + } else { + r[id]->desc=NULL; + } + + if (t->name!=NULL) { + size=strlen(t->name)+1; + r[id]->title=(char*)malloc(size); + if (r[id]->title==NULL) return; + memcpy(r[id]->title,t->name,size); + } else { + r[id]->title=NULL; + } //get external and copy it to the resource path if (t->external!=NULL) { diff --git a/PR/src/xml.c b/PR/src/xml.c index 5f91923..0d46aba 100644 --- a/PR/src/xml.c +++ b/PR/src/xml.c @@ -77,6 +77,7 @@ tTag* getTagStructure() { t->type=NULL; t->value=NULL; t->version=NULL; + t->number=NULL; return t; } @@ -95,6 +96,7 @@ void freeTagStructure(tTag* t) { freeAllocation(t->type); freeAllocation(t->value); freeAllocation(t->version); + freeAllocation(t->number); free(t); } @@ -118,6 +120,8 @@ int attribFill(char* attr,char* val, tTag* t) { FillAttr(t->type,"type"); FillAttr(t->value,"value"); FillAttr(t->version,"version"); + FillAttr(t->number,"levelnumber"); //levelnumber is a number alias + FillAttr(t->number,"number"); return 0; } @@ -448,7 +452,7 @@ void showTag(int n,tTag* t) { #endif -tTag* parseXmlFile(char* vFile,int* error) { +tTag* parseXmlFile(const char* vFile,int* error) { /* error may take the following values: -1 Parse error -2 No memory