Upgraded to Pr 1.0 beta
authorecalot <ecalot>
Wed, 17 Mar 2004 03:19:36 +0000 (03:19 +0000)
committerecalot <ecalot>
Wed, 17 Mar 2004 03:19:36 +0000 (03:19 +0000)
18 files changed:
PR/src/console/main.c
PR/src/lib/actions/classify.c
PR/src/lib/actions/export.c
PR/src/lib/compression/rle_compress.c
PR/src/lib/compression/rle_decompress.c
PR/src/lib/compression/rlev_decompress.c
PR/src/lib/layers/autodetect.c
PR/src/lib/layers/disk.c
PR/src/lib/layers/idlist.c
PR/src/lib/layers/memory.c
PR/src/lib/object/image/image16.c
PR/src/lib/object/image/image2.c
PR/src/lib/object/image/image256.c
PR/src/lib/object/image/image_common.c
PR/src/lib/pr.c
PR/src/lib/xml/search.c
PR/src/lib/xml/tree.c
PR/src/lib/xml/unknown.c

index 2e44111f58c6cea5cf795c2c378939da70bfc744..905be4b787128ea462e7d5a600cdcbfb88f4194f 100644 (file)
@@ -27,6 +27,7 @@ pr.c: Main source file for Princed Resources
        Authors
         Coding & main routines
          Enrique Calot
+         Santiago Zamora
 
         Graphic compression algorithms
          Tammo Jan Dijkema
@@ -46,7 +47,7 @@ pr.c: Main source file for Princed Resources
   DO NOT remove this copyright notice
 */
 
-//Headers
+/* Headers */
 #include <stdio.h>
 #include <string.h>
 
@@ -64,6 +65,9 @@ pr.c: Main source file for Princed Resources
 #ifndef DLL
  #ifdef UNIX
   #include <unistd.h>
+  #ifndef LINUX
+   #include "getopt.h"
+  #endif
  #else
   #include "getopt.h"
  #endif
@@ -73,24 +77,34 @@ pr.c: Main source file for Princed Resources
 |                      Main working functions                   |
 \***************************************************************/
 
+FILE* outputStream=NULL;
+
+#ifdef DLL
+void prSetOutput(FILE* output) {
+       outputStream=output;
+}
+#endif
+
+#ifdef DLL
 int prExportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
-       return prExportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL,"");
+       outputStream=stdout;
+       return prExportDatOpt(vDatFile,vDirName,vResFile,export_flag,NULL,NULL,NULL);
 }
+#endif
 
 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
+                                               if file use it, if directory, 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
+                                               NULL is the default file resources.xml
                        char opt              - program options, see below
-                       char * vDatFileName   - name of the file to be extracted
-                                               NULL means predict it from vDatFile (DISABLED!!!)
+                       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
@@ -104,9 +118,9 @@ int prExportDatOpt(const char* vDatFile, const char* vDirName, const char* vResF
                        verbose_flag   - explain what is being done
                        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,
+                       force_flag     - default option, you cannot disable it,
                                         so please make a backup of your files
-x                      backup_flag    - backup your files
+                       backup_flag    - backup your files
 
 
                Return values:
@@ -120,37 +134,59 @@ x                 backup_flag    - backup your files
                        -7 XML File not found
        */
 
-       //Declare variables
+       /* Declare variables */
        tResource* r[MAX_RES_COUNT];
        int a;
-       const char defaultXmlFile[]=RES_XML_RESOURC_XML;
-       //Set default values
-       if (vResFile==NULL) vResFile=defaultXmlFile; //TODO: Send to prMain or main
-
-       //Parse XML and extract the file //TODO: XML parser outside the function
-       a=parseFile(vResFile,vDatFileName,r);
-       if (a<0) return a-3; //parsing errors
-       a=extract(vDatFile,vDirName,r,opt,vDatFileName,datAuthor);
-       return a; //extracting errors/no errors
+       const char* aux;
+       char* currentDatFileName;
+       char* currentDatFile;
+
+       currentDatFile=strallocandcopy(vDatFileName);
+
+       parseGivenPath(currentDatFile);
+
+       if (vDatFileName==NULL) { /* if no special dat file was specified, a path parsed will be used */
+               aux=getFileNameFromPath(vDatFile);
+       } else {
+               aux=currentDatFile;
+       }
+       currentDatFileName=strallocandcopy(aux);
+
+       /* Parse XML and export the file */
+       a=parseFile(vResFile,currentDatFileName,r);
+       if (a<0) {
+               /* parsing errors */
+               a-=3;
+       } else {
+               /* exporting errors/no errors */
+               a=extract(vDatFile,vDirName,r,opt,currentDatFileName,datAuthor,backupExtension);
+       }
+       free(currentDatFileName);
+       free(currentDatFile);
+       freePartialList();
+
+       return a;
 }
 
+#ifdef DLL
 int prImportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
-       return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,"");
+       outputStream=stdout;
+       return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL);
 }
+#endif
 
 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
+                                               if file use it, if directory, 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
+                       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
@@ -161,9 +197,9 @@ int prImportDatOpt(const char* vDatFile, const char* vDirName, const char* vResF
                        verbose_flag   - explain what is being done
                        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
+                       force_flag     - If not set and the file exists it will prompt
+                                        for action
+                       backup_flag    - backup your files
 
 
                Return values:
@@ -172,146 +208,149 @@ x                       backup_flag    - backup your files
                        -3 No memory
                        -4 XML Attribute not recognized
                        -5 XML File not found
-                       00 File succesfully compiled
+                       00 File successfully imported
                        positive number: number of missing files
        */
 
-       //Declare variables
+       /* Declare variables */
        tResource* r[MAX_RES_COUNT];
        int a;
-       const char defaultXmlFile[]=RES_XML_RESOURC_XML;
+       const char* aux;
+       char* currentDatFileName;
 
-       //Set default values
-       if (vResFile==NULL) vResFile=defaultXmlFile;
+       if (vDatFileName==NULL) { /* if no special dat file was specified, a path parsed will be used */
+               aux=getFileNameFromPath(vDatFile);
+       } else {
+               aux=vDatFileName;
+       }
+       currentDatFileName=strallocandcopy(aux);
 
-       //Parse XML and compile files
-       a=parseFile     (vResFile,vDatFileName,r);
-       if (a<0) return a-1;
-       a=compile (vDatFile, vDirName,r,opt,vDatFileName);
+       /* Parse XML and import files */
+       a=parseFile(vResFile,currentDatFileName,r);
+       if (a<0) {
+               /* parsing errors */
+               a-=1;
+       } else {
+               /* importing errors/no errors */
+               a=compile (vDatFile, vDirName,r,opt,currentDatFileName,backupExtension);
+       }
+       free(currentDatFileName);
        return a;
 }
 
-
 /***************************************************************\
 |                     M A I N   P R O G R A M                   |
 \***************************************************************/
 
-void syntax(FILE* output) {
-       fprintf(output,PARSING_HELP);
+void syntax() {
+       fprintf(outputStream,PARSING_HELP);
 }
 
-int prMain(int* pOption, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
+int prMain(int optionflag, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
 
-       //declare variables
-       int returnValue=1;
-       char* currentDatFileName;
-       const char* aux;
+       /* declare variables */
+       int returnValue;
 
-       if (datfilename==NULL) {
-               aux=getFileNameFromPath(datfile);
-       } else {
-               aux=datfilename;
-       }
-
-       currentDatFileName=strallocandcopy(aux);
+       outputStream=output;
 
-       //do selected tasks
-       if (optionflag&export_flag) {
+       /* do selected tasks */
+       if (hasFlag(export_flag)) { /* Export file */
                char* array[]=PR_TEXT_EXPORT_ARRAY;
-               fprintf(output,"Extracting '%s' to '%s' with %04x\r\n",datfile,dirName,optionflag);
-               returnValue=prExportDatOpt(datfile,dirName,resFile,optionflag,currentDatFileName,datAuthor,extension);
+               fprintf(output,PR_TEXT_TASK_EXTRACT,datfile,dirName);
+               returnValue=prExportDatOpt(datfile,dirName,resFile,optionflag,datfilename,datAuthor,extension);
                fprintf(output,PR_TEXT_RESULT,array[-returnValue],returnValue);
-       }       else if (optionflag&classify_flag) {
+       }       else if (hasFlag(classify_flag)) { /* Classify file */
                char* array[]=PR_TEXT_CLASSIFY_ARRAY;
-               fprintf(output,"Classifing '%s'\r\n",datfile);
+               fprintf(output,PR_TEXT_TASK_CLASSIFY,datfile);
                returnValue=prVerifyDatType(datfile);
-               fprintf(output,PR_TEXT_RESULT,array[2+returnValue],returnValue);
-       }       else if (optionflag&import_flag) {
+               if (hasFlag(cgi_flag)) {
+                       fprintf(output,PR_CGI_TEXT2,returnValue);
+               } else {
+                       fprintf(output,PR_TEXT_RESULT,array[2+returnValue],returnValue);
+               }
+       }       else if (hasFlag(import_flag)) { /* Import file */
                char* array[]=PR_TEXT_IMPORT_ARRAY;
-               fprintf(output,"Compiling '%s' from '%s' with %04x\r\n",datfile,dirName,optionflag);
-               returnValue=prImportDatOpt(datfile,dirName,resFile,optionflag,currentDatFileName,extension);
+               fprintf(output,PR_TEXT_TASK_COMPILE,datfile,dirName);
+               returnValue=prImportDatOpt(datfile,dirName,resFile,optionflag,datfilename,extension);
                if (returnValue<=0) {
                        fprintf(output,PR_TEXT_RESULT,array[-returnValue],returnValue);
                } else {
                        fprintf(output,PR_TEXT_RESULT_ERR,returnValue);
                }
        } else {
-               syntax(output);
+               syntax();
                returnValue=-1;
        }
-       if (currentDatFileName) free(currentDatFileName);
+
        return returnValue;
 }
 
-//Main program
 #ifndef DLL
 
 /***************************************************************\
 |             Standard executable specific functions            |
 \***************************************************************/
 
-int prStart(int* pOption, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
+int prStart(int optionflag, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
        int result=1;
+       whatIs selectedFile;
+       outputStream=output;
 
-       //Do CGI tasks
-       if (optionflag&cgi_flag) {
-               optionflag&=(~classify_flag);
-               if (!(optionflag&first_flag)) {
-                       fprintf(output,PR_CGI_TEXT1);
-                       optionflag|=first_flag;
-               }
-               if (optionflag==cgi_flag) {
-                       fprintf(output,PR_CGI_TEXT2,prVerifyDatType(datfile));
-                       return 1;
-               } else {
-                       optionflag=help_flag;
-               }
-       }
-
-       //Show about
-       if (!(optionflag&first_flag)) {
+       /* Show about or cgi stuff */
+       if (hasFlag(cgi_flag)) {
+               fprintf(output,PR_CGI_TEXT1);
+       } else {
                fprintf(output,PR_ABOUT);
-               optionflag|=first_flag;
        }
 
-       //If bad syntax or help screen requested
-       if (optionflag&help_flag) {
-               syntax(output);
+       /* Show version screen if requested */
+       if (hasFlag(version_flag)) {
+               fprintf(output,PARSING_ABOUT);
                return -1;
        }
 
-       //If version asked, stop
-       if (optionflag&version_flag) {
+       /* If bad syntax or help screen requested */
+       if (hasFlag(help_flag)) {
+               syntax();
                return -1;
        }
 
-       //Perform tasks depending on the argument
-       if (optionflag&import_flag) {
-               //Check out the xml file to get the files to me compiled
+       /* Perform tasks depending on the argument */
+       if (hasFlag(import_flag)) {
+               /* We have to import something, let's see what the parameters are */
                if (datfile==NULL) {
-                       fprintf(output,"Importing all valid dat files from the currect directory\n");
-                       importDir(dirName,resFile,pOption,extension,".",output);
-               } else if (isDir(datfile)!=eFile) {
-                       fprintf(output,"Importing all valid files from given directory\n");
-                       importDir(dirName,resFile,pOption,extension,datfile,output);
-               } else {
-                       result=prMain(pOption,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
+                       /* no files? let's use the whole current directory */
+                       fprintf(output,PR_TEXT_IMPORTING_CURRENT);
+                       importDir(dirName,resFile,optionflag,extension,".",output);
+               } else if ((selectedFile=isDir(datfile))!=eFile) {
+                       fprintf(output,PR_TEXT_IMPORTING_GIVEN);
+                       if ((selectedFile==eDirectory)||(isntADatFile(getFileNameFromPath(datfile),resFile))) {
+                               /* it's a directory or doesn't exist (but it's not a dat file) */
+                               importDir(dirName,resFile,optionflag,extension,datfile,output);
+                       } else {
+                               /* it doesn't exist but it's a dat file */
+                               result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
+                       }
+               } else { /* it's only one existent file */
+                       result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
                }
        } else {
-
-               //Recursive testing for export/classify
+               /* We have to export/classify something, perhaps we'll need to use somerecursive functions */
                if (datfile==NULL) {
+                       /* If nothing, let's use the current dir and check for all the files there */
                        fprintf(output,PR_TEXT_SCANNING_CURRENT);
-                       recurseDirectory(".",pOption,extension,dirName,resFile,datfilename,datAuthor,output);
-               } else if (isDir(datfile)==eDirectory) {
+                       recurseDirectory(".",optionflag,extension,dirName,resFile,datfilename,datAuthor,output);
+               } else if ((selectedFile=isDir(datfile))==eDirectory) {
+                       /* If it's a directory, let's check for all the files there */
                        fprintf(output,PR_TEXT_SCANNING_GIVEN);
-                       recurseDirectory(datfile,pOption,extension,dirName,resFile,datfilename,datAuthor,output);
-               } else if (isDir(datfile)==eNotFound) {
+                       recurseDirectory(datfile,optionflag,extension,dirName,resFile,datfilename,datAuthor,output);
+               } else if (selectedFile==eNotFound) {
+                       /* If the file doesn't exist, print an error and exit */
                        fprintf(output,PR_TEXT_FILE_NOT_FOUND,datfile);
-                       return 0;
+                       result=0;
                } else {
-
-                       result=prMain(pOption,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
+                       /* If it is a file, just do the tasks for it */
+                       result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
                }
        }
 
@@ -324,98 +363,111 @@ int prStart(int* pOption, const char* extension,const char* dirName,const char*
 \***************************************************************/
 
 int main (int argc, char **argv) {
-       //declare variables
-       char* datFileName=NULL;
+       /* declare variables */
        char  dirName[MAX_FILENAME_SIZE]=".";
-       char  extension[MAX_EXTENSION_SIZE]=DEFAULT_BACKUP_EXTENSION;
-       char  resFile[MAX_FILENAME_SIZE]=RES_XML_RESOURC_XML;
+       char* datAuthor  =NULL;
+       char* datFileName=NULL;
        char* datFilePath=NULL;
-       char* datAuthor=NULL;
+       char* extension  =NULL;
+       char* resFile    =NULL;
        int   c;
-       int   flag=0;
+       int   optionflag=0;
 
-       //Parse options
-       while (1) {
+       /* Parse command line options */
+       do {
                static struct option long_options[] = PARSING_OPTIONS;
-
-               /* getopt_long stores the option index here. */
                int junk = 0;
-               c = getopt_long (argc, argv, PARSING_CHARS,long_options,&junk);
-
-               /* Detect the end of the options. */
-               if (c == -1) break;
 
+               c = getopt_long(argc,argv,PARSING_CHARS,long_options,&junk);
                switch (c) {
                                case 'c':
-                                       if (flag&(classify_flag|export_flag)) flag|=help_flag;
-                                       flag|=import_flag;
+                               case 'i':
+                                       if (hasFlag(classify_flag|export_flag)) setFlag(help_flag);
+                                       setFlag(import_flag);
                                        if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
                                        break;
+                               case 'g':
+                                       setFlag(cgi_flag); /* if cgi, a classify must be performed */
                                case 'd':
-                                       if (flag&(import_flag|export_flag)) flag|=help_flag;
-                                       flag|=classify_flag;
+                                       if (hasFlag(import_flag|export_flag)) setFlag(help_flag);
+                                       setFlag(classify_flag);
                                        break;
                                case 'x':
                                case 'e':
-                                       if (flag&(classify_flag|import_flag)) flag|=help_flag;
-                                       flag|=export_flag;
+                                       if (hasFlag(classify_flag|import_flag)) setFlag(help_flag);
+                                       setFlag(export_flag);
                                        if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
                                        break;
                                case 'b':
-                                       flag|=backup_flag;
-                                       if (optarg) strncpy(extension,optarg,MAX_FILENAME_SIZE);
+                                       setFlag(backup_flag);
+                                       freeAllocation(extension);
+                                       extension=strallocandcopy(optarg);
                                        break;
                                case 'f':
-                                       flag|=force_flag;
+                                       setFlag(force_flag);
                                        break;
-                               case 'g':
-                                       flag|=cgi_flag;
-                                       break;
-                               case 'm':
-                                       strncpy(resFile,optarg,MAX_FILENAME_SIZE);
+                               case 's':
+                                       freeAllocation(resFile);
+                                       resFile=strallocandcopy(optarg);
                                        break;
                                case 'r':
-                                       flag|=raw_flag;
+#ifndef PR_IGNORE_RAW_OPTION
+                                       setFlag(raw_flag);
                                        break;
+#endif
                                case 'R':
-                                       flag|=recursive_flag;
+                                       setFlag(recursive_flag);
                                        break;
                                case 't':
-                                       if (datFileName!=NULL) free(datFileName);
+                                       freeAllocation(datFileName);
                                        datFileName=strallocandcopy(optarg);
                                        break;
                                case 'a':
-                                       if (datAuthor!=NULL) free(datAuthor);
+                                       freeAllocation(datAuthor);
                                        datAuthor=strallocandcopy(optarg);
                                        break;
                                case 'v':
-                                       flag|=verbose_flag;
-                                       break;
-                               case 1:
-                                       flag|=version_flag;
+                                       setFlag(verbose_flag);
                                        break;
                                case 2:
-                                       flag|=unknown_flag;
+                                       setFlag(unknown_flag);
+                               case -1:
                                        break;
+                               case 1:
+                                       setFlag(version_flag);
                                default:
-                                       flag|=help_flag;
+                                       setFlag(help_flag);
                }
-       }
+       } while (c!=-1);
 
        if (optind < argc) {
-               datFilePath=argv[optind];
+               int size;
+               datFilePath=strallocandcopy(argv[optind]);
+               /* Erase the last "/" if exists. TODO: send to parseGivenPath  */
+               size=strlen(datFilePath);
+               if (size>0) {
+                       size--;
+                       if (isDirSep(datFilePath,size)) datFilePath[size]=0;
+               }
        }
 
-       if (!flag) flag=help_flag;
+       /* At least one of these options must be selected, if not, the user needs help! */
+       if (!(hasFlag(import_flag|export_flag|classify_flag))) setFlag(help_flag);
 
-       //Run main program
-fld("a");
-       prStart(&flag,extension,dirName,resFile,datFilePath,datFileName,datAuthor,stdout);
-fld("b");
-       //Free memory and exit
-       if (datAuthor!=NULL) free(datAuthor);
-       if (datFileName!=NULL) free(datFileName);
-  return 0;
+       parseGivenPath(datFilePath);
+
+       /* Run main program */
+       prStart(optionflag,extension,dirName,resFile,datFilePath,datFileName,datAuthor,stdout);
+
+       /* Free memory and exit */
+       freePartialList();
+       freeAllocation(datAuthor);
+       freeAllocation(datFileName);
+       freeAllocation(datFilePath);
+       freeAllocation(extension);
+       freeAllocation(resFile);
+
+       return 0;
 }
 
 #endif
@@ -425,8 +477,9 @@ fld("b");
 \***************************************************************/
 
 #ifdef SO
-//When compiling in Unix SO libraries
+/* When compiling in Unix SO libraries */
 void start() {}
 #endif
 
 
+
index 2782d0f69ba7678b33466dd5cb07e6d854dbc8ae..7015efb98a1c36c26e5ef55b68c36af4b0eb8233 100644 (file)
@@ -19,7 +19,7 @@
 */
 
 /*
-tasks.c: Princed Resources : Other DAT file handling tasks
+tasks.c: Princed Resources : Classify a DAT file
 ¯¯¯¯¯¯¯
  Copyright 2003 Princed Development Team
   Created: 24 Aug 2003
@@ -32,61 +32,91 @@ tasks.c: Princed Resources : Other DAT file handling tasks
 */
 
 #include <stdio.h>
-#include "tasks.h"
+#include "tasks.h" /* TODO: rename tasks to classify */
 #include "memory.h"
 #include "resources.h"
+#include "dat.h"
+#include "xmlparse.h"
+#include "xmlsearch.h"
+#include "pr.h"
 
 /***************************************************************\
 |                    Get the type of a DAT file                 |
 \***************************************************************/
 
+#ifndef IGNOREVERIFYDATTYPES
+
+extern int pop1;
+
 int prVerifyDatType(const char* vFiledat) {
+       int                error;
+       int                indexNumber;
+       long int           id;
+       unsigned char*     data;
+       unsigned long  int size;
+       int                type=RES_TYPE_BINARY;
+       unsigned short int numberOfItems;
+
+       /* Initialize abstract variables to read this new DAT file */
+       if (error=mReadBeginDatFile(&numberOfItems,vFiledat)) return error;
+
+       /* main loop */
+       for (indexNumber=0;(indexNumber<numberOfItems)&&type!=RES_TYPE_BINARY;indexNumber++) {
+               id=mReadGetFileInDatFile(indexNumber,&data,&size);
+               if (id<0) return 0; /* Read error */
+               if (id==0xFFFF) continue; /* Tammo Jan Bug fix */
+               if (id>=MAX_RES_COUNT) return 0; /* A file with an ID out of range will be treated as invalid */
+               type=verifyHeader(data,size);
+       }
+       mReadCloseDatFile();
+       return pop1?type:(type+10);
+}
 
-       //Variables
+#if 0
+       /* Variables */
        FILE*              fp;
-  char               ok;
-  int                                       k;
+       char               ok;
+       int                                          k;
 
-       //variables in case header is ok
+       /* variables in case header is ok */
        unsigned short int offset;
        unsigned long  int size;
        unsigned char*     data;
        unsigned char      type=5;
 
-       //loop variables
+       /* loop variables */
        unsigned long  int indexOffset;
        unsigned short int indexSize;
        unsigned short int numberOfItems;
        unsigned char*     index;
 
 
-       if (ok=((fp=fopen(vFiledat,"rb"))!=NULL)) {
-               //verify dat format
+       if ((ok=(((fp=fopen(vFiledat,"rb")))!=NULL))) {
+               /* verify dat format */
                ok    = fread(&indexOffset,4,1,fp);
                ok=ok&& fread(&indexSize,2,1,fp);
                ok=ok&& !fseek(fp,indexOffset,SEEK_SET);
                ok=ok&& fread(&numberOfItems,2,1,fp);
                if (!ok) {
                        fclose(fp);
-                       return 0; //this is not a valid prince dat file
+                       return 0; /* this is not a valid prince dat file */
                }
                if ((numberOfItems*8+2)!=indexSize) {
                        indexOffset+=indexSize;
                        fseek(fp,0,SEEK_END);
-//printf("jaaaj %d %d\r\n",indexOffset,ftell(fp));
-                       ok=(((unsigned long)ftell(fp))==indexOffset)?11:0; //see if it is a pop2 file
+                       ok=(((unsigned long)ftell(fp))==indexOffset)?11:0; /* see if it is a pop2 file */
                        fclose(fp);
-                       return ok; //this is a pop2 dat file or invalid
+                       return ok; /* this is a pop2 dat file or invalid */
                }
                if ((index=getMemory(indexSize-2))==NULL) {
                        fclose(fp);
-                       return -2; //no memory
+                       return -2; /* no memory */
                }
                ok=fread(index,indexSize-2,1,fp);
 
-               //main loop
+               /* main loop */
                for (k=0;ok&&(k<numberOfItems)&&(type==5);k++) {
-                       //for each archived file
+                       /* for each archived file */
                        ok=ok&&!(index[k*8+4]||index[k*8+5]);
                        offset=index[k*8+2]+256*index[k*8+3];
                        size=index[k*8+6]+256*index[k*8+7]+1;
@@ -94,14 +124,46 @@ int prVerifyDatType(const char* vFiledat) {
                        ok=ok&&(!fseek(fp,offset,SEEK_SET));
                        ok=ok&&fread(data,size,1,fp);
 
-                       //set resource information on this index entry
+                       /* set resource information on this index entry */
                        type=verifyHeader(data,(unsigned short int)size);
 
                }
                fclose(fp);
-               return ok?type:-1;
+               return ok?type:0;
        } else {
-               return -1; //file could not be open
+               return -1; /* file could not be open */
        }
 }
+#endif
+#else
+extern FILE* outputStream;
+void showTag(int n,tTag* t);
+void compareFiles(const char* vModified,const char* vOriginal) {
+       /* Declare variables */
+       int error;
+       tTag* modified;
+       tTag* original;
+
+       /* Parse modified file */
+       modified=parseXmlFile(vModified,&error);
+       fprintf(outputStream,"Modified file parsing result: %d\n",error);
+
+       /* Parse original file */
+       original=parseXmlFile(vOriginal,&error);
+       fprintf(outputStream,"Original file parsing result: %d\n",error);
+
 
+       fprintf(outputStream,"Original tree\n");
+       showTag(0,original);
+       fprintf(outputStream,"Modified tree\n");
+       showTag(0,modified);
+
+
+       /* Compare */
+       compareXmlFile(modified,original);
+
+       /* Free memory */
+       freeTagStructure(modified);
+       freeTagStructure(original);
+}
+#endif
index a639f827d0e26f1c51fe27e2dfd1c1bdf4d510b2..35ae492d061e6a8422534b448cefaad1a8615a8a 100644 (file)
 /*
 extract.c: Princed Resources : DAT Extractor
 ¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 1.20 (2004-Mar-07)
+  Version: 1.30 (2004-Mar-15)
 
  Note:
   DO NOT remove this copyright notice
@@ -33,10 +35,10 @@ extract.c: Princed Resources : DAT Extractor
 
 #include <stdio.h>
 #include <string.h>
-
 #include "pr.h"
 
 #include "extract.h"
+#include "dat.h"
 #include "disk.h"
 #include "memory.h"
 
@@ -46,184 +48,140 @@ extract.c: Princed Resources : DAT Extractor
 #include "plv.h"
 #include "mid.h"
 
+extern FILE* outputStream;
+
 /***************************************************************\
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
 
-
-
+#define initializePaletteList \
+for (id=0;id<MAX_RES_COUNT;id++) {\
+       if (r[id]!=NULL) {\
+               r[id]->palAux=NULL;\
+       }\
+}
 
 /***************************************************************\
-|                     M A I N   E X T R A C T                   |
+|                    M A I N   E X T R A C T                    |
 \***************************************************************/
 
+
 /*
        Extracts a dat file
        For parameter documentation, see pr.c
 */
 
-int extract(const char* vFiledat,const char* vDirExt, tResource* r[], int task, const char* vDatFileName, const char* vDatAuthor) {
-
-       //Variables
-       char          vFileext[260];
-       FILE*         fp;
-       int           ok,pop1;
-
-       if (ok=((fp=fopen(vFiledat,"rb"))!=NULL)) {
-               //loop variables
-               unsigned long  int indexOffset;
-               unsigned short int indexSize,numberOfItems;
-               unsigned char*     index;
-               int                ofk=0;
-               int                k;
-
-               //if header ok, new variables
-               char               recordSize;
-               char               type=0;
-               tImage             image; //this is used to make a persistent palette
-               unsigned char*     data;
-               unsigned long  int size,offset;
-               unsigned short int id;
-               unsigned short int paletteId=0;
-
-               //verify dat format
-               ok    = fread(&indexOffset,4,1,fp);
-               ok=ok&& fread(&indexSize,2,1,fp);
-               ok=ok&& !fseek(fp,indexOffset,SEEK_SET);
-               ok=ok&& fread(&numberOfItems,2,1,fp);
-               pop1=((numberOfItems*8+2)==indexSize);
-
-               if (!pop1) { //verify if pop2
-                       ofk=numberOfItems*6+2+(numberOfItems-2)*13;
-                       numberOfItems=((indexSize-6-(numberOfItems*6)-((numberOfItems-2)*13))/11);
-               }
-               recordSize=pop1?8:11;
-               if (!ok) {
-                       fclose(fp);
-                       return -3; //this is not a valid prince dat file
-               }
-               if ((index=getMemory(indexSize-2))==NULL) {
-                       fclose(fp);
-                       return -2; //no memory
-               }
+int extract(const char* vFiledat,const char* vDirExt, tResource* r[], int optionflag, const char* vDatFileName, const char* vDatAuthor,const char* backupExtension) {
+       char               vFileext[MAX_FILENAME_SIZE];
+       int                indexNumber;
+       int                ok;
+       long int           id;
+       tImage             image; /* this is used to make a persistent palette */
+       unsigned char*     data;
+       unsigned long  int size;
+       unsigned short int numberOfItems;
+       unsigned short int paletteId=0;
 
-               ok=fread(index,indexSize-2,1,fp);
+       /* Initialize abstract variables to read this new DAT file */
+       if (ok=mReadBeginDatFile(&numberOfItems,vFiledat)) return ok;
 
-               //Initializes the palette list
-               for (id=0;id<MAX_RES_COUNT;id++) {
-                       if (r[id]!=NULL) {
-                               r[id]->palAux=NULL;
-                       }
-               }
+       /* Initializes the palette list */
+       initializePaletteList;
 
-               //main loop
-               for (k=0;ok&&(k<numberOfItems);k++) {
-                       //for each archived file the index is read
-                       id=index[ofk+k*recordSize]+256*index[ofk+k*recordSize+1];
-                       offset=index[ofk+k*recordSize+2]+256*index[ofk+k*recordSize+3]+256*256*index[ofk+k*recordSize+4]+256*256*256*index[ofk+k*recordSize+5];
-                       size=index[ofk+k*recordSize+6]+256*index[ofk+k*recordSize+7]+1;
-                       if (!pop1) {
-                               ok=ok&&(index[ofk+k*recordSize+8]==0x40)&&(!index[ofk+k*recordSize+9])&&(!index[ofk+k*recordSize+10]);
-                       }
-                       ok=ok&&((data=getMemory(size))!=NULL);
-                       ok=ok&&(!fseek(fp,offset,SEEK_SET));
-                       ok=ok&&fread(data,size,1,fp);
-                       if (!ok) return -3;
-                       //End of index reading
-
-                       //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]->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);
-                       }
+       /* main loop */
+       ok=1;
+       for (indexNumber=0;ok&&(indexNumber<numberOfItems);indexNumber++) {
+               id=mReadGetFileInDatFile(indexNumber,&data,&size);
+
+               if (id<0) return -3; /* Read error */
+               if (id==0xFFFF) continue; /* Tammo Jan Bug fix */
+               if (id>=MAX_RES_COUNT) return -3; /* A file with an ID out of range will be treated as invalid */
 
-                       if (!(task&unknown_flag)) { //If unknown flag is set do nothing but generate the unknown.xml file
-                               //select type
-                               if (task&raw_flag) (*(r[id])).type=0; //If "extract as raw" is set, type is 0
+               /* set resource information on this index entry */
+               if (mReadInitResource(r+id,data,size)) return -2;
 
-                               //save file
-                               getFileName(vFileext,vDirExt,r[id],id,vFiledat,vDatFileName);
+               if ((r[id]->type==RES_TYPE_PALETTE)||isInThePartialList(r[id]->path,id)) { /* If the resource was specified or is a palette, do the tasks */
+                       if (!(hasFlag(unknown_flag))) { /* If unknown flag is set do nothing but generate the unknown.xml file */
+                               if (hasFlag(raw_flag)) r[id]->type=0; /* If "extract as raw" is set, type is 0 */
 
-                               if (task&verbose_flag) printf("Extracting '%s'...\n",getFileNameFromPath(vFileext));
+                               /* get save file name (if unknown document it in the xml) */
+                               getFileName(vFileext,vDirExt,r[id],(unsigned short)id,vFiledat,vDatFileName,optionflag,backupExtension);
 
                                switch (r[id]->type) {
-                                       case 1:
-                                               ok=ok&&mFormatExtractPlv(data,vFileext,size,r[id]->number,vDatFileName,r[id]->title,r[id]->desc,vDatAuthor);
+                                       case RES_TYPE_LEVEL:
+                                               ok=ok&&mFormatExportPlv(data,vFileext,size,r[id]->number,vDatFileName,r[id]->name,r[id]->desc,vDatAuthor,optionflag,backupExtension);
                                                break;
-                                       case 5:
-                                       case 0: //Raw files
-                                               ok=ok&&writeData(data,1,vFileext,size); //Ignore checksum
+                                       case RES_TYPE_BINARY: /* Binary files */
+                                       case RES_TYPE_RAW: /* Raw files */
+                                               ok=ok&&writeData(data,1,vFileext,size,optionflag,backupExtension); /* Ignore checksum */
                                                break;
-                                       case 6: //save and remember palette file
-                                               //This will remember the palette for the next images
-                                               r[id]->palAux=(unsigned char*)malloc(size);
+                                       case RES_TYPE_PALETTE: /* save and remember palette file */
+                                               /* This will remember the palette for the next images */
+                                               r[id]->palAux=getMemory(size);
                                                memcpy(r[id]->palAux,data,size);
-                                               if (!paletteId) { //In case there is no loaded palettes, then load immediately the first found palette to clear garbage
-                                                       mLoadPalette(data,&image);
+                                               if (!paletteId) { /* In case there is no loaded palettes load immediately the first found palette to clear garbage */
+                                                       mLoadPalette(data,image);
                                                        paletteId=id;
                                                }
-                                               //This will extract the palette
-                                               ok=ok&&mFormatExtractPal(&data,vFileext,size);
+                                               /* This will export the palette */
+                                               if (isInThePartialList(r[id]->path,id))  /* If the palette was specified extract it */
+                                                       ok=ok&&mFormatExportPal(data,vFileext,size,optionflag,backupExtension);
                                                break;
-                                       case 7: //save pcs file
-                                       case 4: //save midi file
-                                               ok=ok&&mFormatExtractMid(data,vFileext,size);
+                                       case RES_TYPE_PCSPEAKER: /* save pcs file */
+                                       case RES_TYPE_MIDI:     /* save midi file */
+                                               ok=ok&&mFormatExportMid(data,vFileext,size,optionflag,backupExtension);
                                                break;
-                                       case 3: //save wav file
-                                               ok=ok&&mFormatExtractWav(data,vFileext,size);
+                                       case RES_TYPE_WAVE: /* save wav file */
+                                               ok=ok&&mFormatExportWav(data,vFileext,size,optionflag,backupExtension);
                                                break;
-                                       case 2: //save image
-                                               //Palette handling
-
-                                               if (r[id]->palette!=paletteId) { //The palette isn't the already loaded
-                                                       if (r[id]->palette) { //We need a palette
+                                       case RES_TYPE_IMAGE: /* save image */
+                                               /* Palette handling */
+                                               if (r[id]->palette!=paletteId) { /* The palette isn't the already loaded */
+                                                       if (r[id]->palette) { /* We need a palette */
                                                                /*
                                                                        We need a palette and it is not the palette we have loaded in memory
                                                                        So a new palette is going to be loaded.
                                                                */
-                                                               if ((r[r[id]->palette]->palAux)!=NULL) { //If this palette wasn't loaded, it becomes loaded
-                                                                       mLoadPalette(r[r[id]->palette]->palAux,&image);
-                                                                       paletteId=r[id]->palette; //sets the new palette loaded
+                                                               if ((r[r[id]->palette]->palAux)!=NULL) { /* If this palette wasn't loaded, it becomes loaded */
+                                                                       mLoadPalette(r[r[id]->palette]->palAux,image);
+                                                                       paletteId=r[id]->palette; /* sets the new palette loaded */
                                                                }
                                                        }
                                                }
-
-                                               //Extract bitmap
-                                               ok=ok&&mFormatExtractBmp(data,vFileext,size,image);
+                                               /* Export bitmap */
+                                               ok=ok&&mFormatExportBmp(data,vFileext,size,image,optionflag,backupExtension);
                                                break;
                                }
-                       }
-                       if (data!=NULL) free(data);
-               }
-               fclose(fp);
-
-               //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);
+                               /* Verbose information */
+                               if (hasFlag(verbose_flag)) {
+                                       if (ok) {
+                                               fprintf(outputStream,PR_TEXT_EXPORT_WORKING,getFileNameFromPath(vFileext));
+                                       } else {
+                                               fprintf(outputStream,PR_TEXT_EXPORT_ERROR,getFileNameFromPath(vFileext));
+                                       }
                                }
+                       } else {
+                               /* if the dat file is unknown, add it in the xml */
+                               getFileName(vFileext,vDirExt,r[id],(unsigned short)id,vFiledat,vDatFileName,optionflag,backupExtension);
                        }
+                       //freeAllocation(data);
                }
+       }
 
-               //Close unknownXML
-               endUnknownXml();
-               return ok-1;
-       } else {
-               return -1; //file could not be open
+       /* Free allocated resources, dynamic strings and the index */
+       for (id=0;id<MAX_RES_COUNT;id++) {
+               if (r[id]!=NULL) {
+                       freeAllocation(r[id]->palAux);
+                       freeAllocation(r[id]->desc);
+                       freeAllocation(r[id]->name);
+                       freeAllocation(r[id]->path);
+                       free(r[id]);
+               }
        }
+       mReadCloseDatFile();
+
+       /* Close unknownXML */
+       endUnknownXml(optionflag,backupExtension);
+       return ok-1;
 }
+
index 10e34a16128c09ca11b945e5a2ba5aa3629d4296..8497f6fc64a6baeaa14a859627f916685ae4a55e 100644 (file)
 */
 
 /*
-compress.c: Princed Resources : Image Compressor
+compress.c: Princed Resources : Image Compression Library
 ¯¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 2.00 (2004-Mar-07)
 
  Note:
   DO NOT remove this copyright notice
@@ -39,71 +40,125 @@ compress.c: Princed Resources : Image Compressor
 #include <string.h>
 #include "compress.h"
 #include "memory.h"
-
-//reserved memory for the Lzx algorithm
-#define MAX_MOD_SIZE_IN_LZX 32001                     /* 38401 */
-//modulus to be used in the 10 bits of the algorithm
-#define MAX_MXD_SIZE_IN_LZX 0x400
+#include "pr.h"
 
 /***************************************************************\
-|                Compression algorithm handling                 |
+|                        Image transpose                        |
 \***************************************************************/
 
-//Determines where the transposed byte must be saved
-int transpose(int x,int n,int m) {
-       return ((x%m)*((n+1)/2))+(int)(x/m);
+/* Determines where the transposed byte must be saved */
+int transpose(int x,int w,int h) {
+       return ((x%h)*(w))+(int)(x/h);
+}
+
+void transposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[transpose(cursor,image->widthInBytes,image->height)]=image->pix[cursor];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
 }
 
-//B3 and B4 expansion algorithm sub function
+void antiTransposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[cursor]=image->pix[transpose(cursor,image->widthInBytes,image->height)];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
+}
+
+/***************************************************************\
+|                    Uncompression algorithms                   |
+\***************************************************************/
+
+/* LZG expansion algorithm sub function */
 unsigned char popBit(unsigned char *byte) {
-  unsigned char bit=(unsigned char)((*byte)&1);
-  (*byte)>>=1;
-  return bit;
+       unsigned char bit=(unsigned char)((*byte)&1);
+       (*byte)>>=1;
+       return bit;
 }
 
-//Expands B3/B4 algorithm
-void expandLzx(unsigned /* note: if error remove signed */char* array,tImage* img, int *i,int cursor, int virtualSize) {
+/* Expands LZ Groody algorithm. This is the core of PR */
+int expandLzg(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
        char k;
-       int pos,h;
+       int location,h,cursor=0,pos=0;
        unsigned char maskbyte,rep;
 
-       for(pos=0;pos<MAX_MXD_SIZE_IN_LZX;(*img).pix[pos]=0,pos++); //clean output garbage
-       while (cursor<virtualSize) {
-               maskbyte=array[*i];(*i)++;
-               for (k=8;k&&(cursor<virtualSize);k--) {
+       if ((image->pix=getMemory(/*imageSize*/MAX_MOD_SIZE_IN_LZG))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+       for(location=0;location<MAX_MOD_SIZE_IN_LZG;image->pix[location]=0,location++); /* clean output garbage */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               maskbyte=array[pos++];
+               for (k=8;k&&(cursor<imageSize);k--) {
                        if (popBit(&maskbyte)) {
-                               (*img).pix[cursor]=array[*i];(*i)++;cursor++;
+                               image->pix[cursor++]=array[pos++];
                        } else {
-                               pos=66+((0x100)*((rep=array[*i])&3))+(unsigned char)array[(*i)+1];(*i)+=2;
+                               location=66+(((rep=array[pos])&3)<<8)+(unsigned char)array[pos+1];pos+=2;
                                rep=(unsigned char)((rep>>2)+3);
-                               while (rep--) { //Be careful in big images
-                                       h=cursor/MAX_MXD_SIZE_IN_LZX-(pos%MAX_MXD_SIZE_IN_LZX>cursor%MAX_MXD_SIZE_IN_LZX);
-                                       (*img).pix[cursor]=(*img).pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZX+pos%MAX_MXD_SIZE_IN_LZX];cursor++;pos++;
+                               while (rep--) { /* Be careful in big images */
+                                       h=cursor/MAX_MXD_SIZE_IN_LZG-((location%MAX_MXD_SIZE_IN_LZG)>(cursor%MAX_MXD_SIZE_IN_LZG));
+                                       image->pix[cursor++]=image->pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZG+(location++)%MAX_MXD_SIZE_IN_LZG];
+
+//                                     h=((cursor-(location&0x3FF))&(~0x3FF));
+//                                     image->pix[cursor]=image->pix[((h<0)?0:h)+(location&0x3FF)];
+       //                              cursor++;location++;
                                }
                        }
                }
        }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
+}
+
+/* Expands RLE algorithm */
+int expandRle(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
+       int cursor=0;
+       register signed char rep;
+       int pos=0;
+
+       if ((image->pix=getMemory(imageSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               rep=(signed char)(array[pos++]);
+               if (rep<0) {
+                       /* Negative */
+                       while (rep++) image->pix[cursor++]=array[pos];
+                       pos++;
+               } else {
+                       /* Positive */
+                       rep=~rep;
+                       while (rep++) image->pix[cursor++]=array[pos++];
+               }
+       }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
 }
 
-//Compress B1/B2 algorithm
+/***************************************************************\
+|                    Compression algorithms                     |
+\***************************************************************/
+
+/* Compress using the Run Length Encoding algorithm */
 void compressRle(unsigned char* data,tImage* img,int *dataSize) {
-       //Declare pointers
+       /* Declare pointers */
        unsigned char* cursorData  = data;
        char*          counter;
-       unsigned char* cursorPix   = (*img).pix;
-       unsigned char* imgEnd      = (*img).pix+(*dataSize);
+       unsigned char* cursorPix   = img->pix;
+       unsigned char* imgEnd      = img->pix+(*dataSize);
 
        while (cursorPix<imgEnd) {
-               //Step 1: Create counter
+               /* Step 1: Create counter */
                *(counter=(char*)(cursorData++))=-1;
 
-               //Step 2: Look and copy the string until a repeated byte is found
+               /* Step 2: Look and copy the string until a repeated byte is found */
                while (
                        (cursorPix<imgEnd)&&
                        (
                                (*cursorPix!=*(cursorPix+1))||
                                (
-                                       (*cursorPix==*(cursorPix+1))&&
+                                       /*(*cursorPix==*(cursorPix+1))&&*/
                                        ((cursorPix+1)<imgEnd)&&
                                        (*cursorPix!=*(cursorPix+2))
                                )
@@ -116,169 +171,154 @@ void compressRle(unsigned char* data,tImage* img,int *dataSize) {
                        cursorData++;
                }
 
-               //Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions
+               /* Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions */
                if (*counter==-1) {
-                       while ((cursorPix<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
+                       while ((cursorPix+1<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
                                cursorPix++;
                                (*counter)--;
                        }
 
-                       *(cursorData)=*(cursorPix); //Print repeated char
+                       *(cursorData)=*(cursorPix); /* Print repeated char */
                        cursorPix++;
                        cursorData++;
                }
        }
+
        *(cursorData++)=0;
        *(cursorData++)=*(cursorPix);
-       *dataSize=(int)((long int)cursorData-(long int)data); //Note: casted to long for portability with 64 bits architectures
+       *dataSize=(int)((long int)cursorData-(long int)data)-2; /* Note: casted to long for portability with 64 bits architectures */
 }
 
-//Expands an array into an image
-int mExpandGraphic(unsigned char* array,tImage *image, int virtualSize) {
-       /*
-               Reads array and extracts tImage
-               returns the next image address or -1 in case of error
+/***************************************************************\
+|               Main compress and expand graphics               |
+\***************************************************************/
 
+/*
                Header info:
-                char checksum, short int height, short int width, (char)0, char compressionType
-                normaly: (* ignored types)
-                checksum* - height - 00 - width - 00 - 00* - compression type
+                1 byte  - checksum           char checksum
+                2 bytes - height             short int height
+                2 bytes - width              short int width
+                1 byte  - 00                 (char)0
+                1 byte  - compression type   unsigned char compressionType
+*/
+
+/* Expands an array into an image */
+int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes) {
+       /*
+               Reads data and extracts tImage
+               returns the next image address or -1 in case of error
        */
 
-  int cursor=0;
-  int i=1;
-
-  //Get memory for the image
-       image->height=((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]) ;
-       i=i+2;
-       image->width =((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]);
-       i=i+2;
-       (*image).size  =(*image).height*(*image).width;
-       virtualSize=(((*image).height*((*image).width+((*image).width&1)))>>1);
-       i++;
-
-  switch ((unsigned char)array[i++]) {
-               case PG_COMP_RAW: //No Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               (*image).pix[cursor++]=array[i++];
-                       }
+       int imageSizeInBytes;
+       int result;
+
+       data++;
+       image->height=((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+       image->width =((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+
+       if (*(data++)) return -1; /* Verify format */
+       image->type=(unsigned char)(*(data++));
+       dataSizeInBytes-=7;
+
+       if (image->type&0xB0) {
+               image->widthInBytes=(image->width+1)/2;
+       } else {
+               image->widthInBytes=(image->width+7)/8;
+       }
+       imageSizeInBytes=image->widthInBytes*image->height;
+
+       switch (getAlgor(image->type)) {
+               case COMPRESS_RAW: /* No Compression Algorithm */
+                       if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+                       memcpy(image->pix,data,imageSizeInBytes);
+                       result=COMPRESS_RESULT_SUCCESS;
                        break;
-               case PG_COMP_RLE_LR: //RLE Left to Right Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(cursor++)]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[(cursor++)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_RLE_UD: //RLE Up to Down Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(transpose(cursor++,(*image).width,(*image).height))]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[transpose(cursor++,(*image).width,(*image).height)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_LR: //LZ Groody Up to Down Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       expandLzx(array,image,&i,cursor,virtualSize);
+               case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_UD: //LZ Groody Left to Right Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       {
-                       unsigned char* outputaux=getMemory(virtualSize);
-                       expandLzx(array,image,&i,cursor,virtualSize);
-                       //Transpose
-                 while (cursor<virtualSize) outputaux[transpose(cursor,(*image).width,(*image).height)]=(*image).pix[cursor++];
-                       free((*image).pix);
-                       (*image).pix=outputaux;
-                       }
+               case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
                default:
-                return -1;
+                       result=COMPRESS_RESULT_FATAL;
+                       break;
        }
-       return i;
+       return result; /* Ok */
 }
 
-#define COMPRESS_WORKING_ALGORITHMS 3
-
-//Compress an image into an array
-int mCompressGraphic(unsigned char* data,tImage* i, int* size) {
-       //Declare variables
+/* Compress an image into binary data */
+int mCompressGraphic(unsigned char* data,tImage* image, int* dataSizeInBytes) {
+       /* Declare variables */
+       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
        int            compressedSize [COMPRESS_WORKING_ALGORITHMS];
        int            algorithm;
-       int            cursor;
-       int            virtualsize;
-       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
-       unsigned char* outputaux;
-
-       //Initialize variables
-       virtualsize=(((i->width)+1)>>1)*i->height;
-       outputaux=getMemory(virtualsize);
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) compressedSize[cursor]=virtualsize;
-       cursor=0;
-
-       //B0
-       compressed[0]=getMemory(compressedSize[0]);
-       memcpy(compressed[0],i->pix,compressedSize[0]);
-
-       //B1
-       compressed[1]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       compressRle(compressed[1],i,&(compressedSize[1]));
-
-       //B2
-       compressed[2]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       //Transpose
-  while (cursor<=virtualsize) {
-               outputaux[cursor]=i->pix[transpose(cursor,i->width,i->height)];
-               cursor++;
-       }
-       free(i->pix);
-       i->pix=outputaux;
-       compressRle(compressed[2],i,&(compressedSize[2]));
-
-       /*Process results*/
-
-       //Select the best compression (find minimum)
-       *size=compressedSize[0];
-       algorithm=0;
-       for (cursor=1;cursor<3;cursor++) {
-               if ((*size)>compressedSize[cursor]) {
-                       (*size)=compressedSize[cursor];
-                       algorithm=cursor;
+       int            i;
+       int            imageSizeInBytes;
+
+       /* Initialize variables */
+       imageSizeInBytes=image->widthInBytes*image->height;
+       for (i=0;i<COMPRESS_WORKING_ALGORITHMS;i++) compressedSize[i]=imageSizeInBytes;
+
+       /*
+               Perform all compressions
+       */
+
+       /* COMPRESS_RAW */
+       compressed[COMPRESS_RAW]=getMemory(compressedSize[COMPRESS_RAW]);
+       memcpy(compressed[COMPRESS_RAW],image->pix,compressedSize[COMPRESS_RAW]);
+
+       /* COMPRESS_RLE_LR */
+       compressed[COMPRESS_RLE_LR]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       compressRle(compressed[COMPRESS_RLE_LR],image,&(compressedSize[COMPRESS_RLE_LR]));
+
+       /* COMPRESS_RLE_UD */
+       compressed[COMPRESS_RLE_UD]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       antiTransposeImage(image,imageSizeInBytes);
+       compressRle(compressed[COMPRESS_RLE_UD],image,&(compressedSize[COMPRESS_RLE_UD]));
+
+       /*
+               Process results
+       */
+
+       /* Select the best compression (find minimum) */
+       *dataSizeInBytes=compressedSize[COMPRESS_RAW];
+       algorithm=COMPRESS_RAW;
+       for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+               if ((*dataSizeInBytes)>compressedSize[i]) {
+                       (*dataSizeInBytes)=compressedSize[i];
+                       algorithm=i;
                }
        }
 
-       //Copy the best algorithm in the compressed data
-       memcpy(data+6,compressed[algorithm],*size);
-       (*size)+=6;
-
-       //Write header
-       //(16 bits)height (Intel short int format)
-       data[0]=i->height;
-       data[1]=i->height>>8;
-       //(16 bits)width (Intel short int format)
-       data[2]=i->width;
-       data[3]=i->width>>8;
-       //(12 bits)000000001011+(4 bits)algorithm
-       data[4]=0;
-       data[5]=0xB0+algorithm;
+       /* Copy the best algorithm in the compressed data */
+       memcpy(data+6,compressed[algorithm],*dataSizeInBytes);
+       (*dataSizeInBytes)+=6;
 
-       //Free all compression attempts
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) free(compressed[cursor]);
+       /*
+               Write header
+       */
+
+       /* (16 bits)height (Intel short int format) */
+       data[0]=image->height;
+       data[1]=image->height>>8;
+       /* (16 bits)width (Intel short int format) */
+       data[2]=image->width;
+       data[3]=image->width>>8;
+       /* (8 bits)00000000+(4 bits)palette type+(4 bits)algorithm */
+       data[4]=0;
+       data[5]=image->type|algorithm;
 
+       /* Free all compression attempts */
+       for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
        return 1;
 }
index 10e34a16128c09ca11b945e5a2ba5aa3629d4296..8497f6fc64a6baeaa14a859627f916685ae4a55e 100644 (file)
 */
 
 /*
-compress.c: Princed Resources : Image Compressor
+compress.c: Princed Resources : Image Compression Library
 ¯¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 2.00 (2004-Mar-07)
 
  Note:
   DO NOT remove this copyright notice
@@ -39,71 +40,125 @@ compress.c: Princed Resources : Image Compressor
 #include <string.h>
 #include "compress.h"
 #include "memory.h"
-
-//reserved memory for the Lzx algorithm
-#define MAX_MOD_SIZE_IN_LZX 32001                     /* 38401 */
-//modulus to be used in the 10 bits of the algorithm
-#define MAX_MXD_SIZE_IN_LZX 0x400
+#include "pr.h"
 
 /***************************************************************\
-|                Compression algorithm handling                 |
+|                        Image transpose                        |
 \***************************************************************/
 
-//Determines where the transposed byte must be saved
-int transpose(int x,int n,int m) {
-       return ((x%m)*((n+1)/2))+(int)(x/m);
+/* Determines where the transposed byte must be saved */
+int transpose(int x,int w,int h) {
+       return ((x%h)*(w))+(int)(x/h);
+}
+
+void transposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[transpose(cursor,image->widthInBytes,image->height)]=image->pix[cursor];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
 }
 
-//B3 and B4 expansion algorithm sub function
+void antiTransposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[cursor]=image->pix[transpose(cursor,image->widthInBytes,image->height)];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
+}
+
+/***************************************************************\
+|                    Uncompression algorithms                   |
+\***************************************************************/
+
+/* LZG expansion algorithm sub function */
 unsigned char popBit(unsigned char *byte) {
-  unsigned char bit=(unsigned char)((*byte)&1);
-  (*byte)>>=1;
-  return bit;
+       unsigned char bit=(unsigned char)((*byte)&1);
+       (*byte)>>=1;
+       return bit;
 }
 
-//Expands B3/B4 algorithm
-void expandLzx(unsigned /* note: if error remove signed */char* array,tImage* img, int *i,int cursor, int virtualSize) {
+/* Expands LZ Groody algorithm. This is the core of PR */
+int expandLzg(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
        char k;
-       int pos,h;
+       int location,h,cursor=0,pos=0;
        unsigned char maskbyte,rep;
 
-       for(pos=0;pos<MAX_MXD_SIZE_IN_LZX;(*img).pix[pos]=0,pos++); //clean output garbage
-       while (cursor<virtualSize) {
-               maskbyte=array[*i];(*i)++;
-               for (k=8;k&&(cursor<virtualSize);k--) {
+       if ((image->pix=getMemory(/*imageSize*/MAX_MOD_SIZE_IN_LZG))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+       for(location=0;location<MAX_MOD_SIZE_IN_LZG;image->pix[location]=0,location++); /* clean output garbage */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               maskbyte=array[pos++];
+               for (k=8;k&&(cursor<imageSize);k--) {
                        if (popBit(&maskbyte)) {
-                               (*img).pix[cursor]=array[*i];(*i)++;cursor++;
+                               image->pix[cursor++]=array[pos++];
                        } else {
-                               pos=66+((0x100)*((rep=array[*i])&3))+(unsigned char)array[(*i)+1];(*i)+=2;
+                               location=66+(((rep=array[pos])&3)<<8)+(unsigned char)array[pos+1];pos+=2;
                                rep=(unsigned char)((rep>>2)+3);
-                               while (rep--) { //Be careful in big images
-                                       h=cursor/MAX_MXD_SIZE_IN_LZX-(pos%MAX_MXD_SIZE_IN_LZX>cursor%MAX_MXD_SIZE_IN_LZX);
-                                       (*img).pix[cursor]=(*img).pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZX+pos%MAX_MXD_SIZE_IN_LZX];cursor++;pos++;
+                               while (rep--) { /* Be careful in big images */
+                                       h=cursor/MAX_MXD_SIZE_IN_LZG-((location%MAX_MXD_SIZE_IN_LZG)>(cursor%MAX_MXD_SIZE_IN_LZG));
+                                       image->pix[cursor++]=image->pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZG+(location++)%MAX_MXD_SIZE_IN_LZG];
+
+//                                     h=((cursor-(location&0x3FF))&(~0x3FF));
+//                                     image->pix[cursor]=image->pix[((h<0)?0:h)+(location&0x3FF)];
+       //                              cursor++;location++;
                                }
                        }
                }
        }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
+}
+
+/* Expands RLE algorithm */
+int expandRle(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
+       int cursor=0;
+       register signed char rep;
+       int pos=0;
+
+       if ((image->pix=getMemory(imageSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               rep=(signed char)(array[pos++]);
+               if (rep<0) {
+                       /* Negative */
+                       while (rep++) image->pix[cursor++]=array[pos];
+                       pos++;
+               } else {
+                       /* Positive */
+                       rep=~rep;
+                       while (rep++) image->pix[cursor++]=array[pos++];
+               }
+       }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
 }
 
-//Compress B1/B2 algorithm
+/***************************************************************\
+|                    Compression algorithms                     |
+\***************************************************************/
+
+/* Compress using the Run Length Encoding algorithm */
 void compressRle(unsigned char* data,tImage* img,int *dataSize) {
-       //Declare pointers
+       /* Declare pointers */
        unsigned char* cursorData  = data;
        char*          counter;
-       unsigned char* cursorPix   = (*img).pix;
-       unsigned char* imgEnd      = (*img).pix+(*dataSize);
+       unsigned char* cursorPix   = img->pix;
+       unsigned char* imgEnd      = img->pix+(*dataSize);
 
        while (cursorPix<imgEnd) {
-               //Step 1: Create counter
+               /* Step 1: Create counter */
                *(counter=(char*)(cursorData++))=-1;
 
-               //Step 2: Look and copy the string until a repeated byte is found
+               /* Step 2: Look and copy the string until a repeated byte is found */
                while (
                        (cursorPix<imgEnd)&&
                        (
                                (*cursorPix!=*(cursorPix+1))||
                                (
-                                       (*cursorPix==*(cursorPix+1))&&
+                                       /*(*cursorPix==*(cursorPix+1))&&*/
                                        ((cursorPix+1)<imgEnd)&&
                                        (*cursorPix!=*(cursorPix+2))
                                )
@@ -116,169 +171,154 @@ void compressRle(unsigned char* data,tImage* img,int *dataSize) {
                        cursorData++;
                }
 
-               //Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions
+               /* Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions */
                if (*counter==-1) {
-                       while ((cursorPix<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
+                       while ((cursorPix+1<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
                                cursorPix++;
                                (*counter)--;
                        }
 
-                       *(cursorData)=*(cursorPix); //Print repeated char
+                       *(cursorData)=*(cursorPix); /* Print repeated char */
                        cursorPix++;
                        cursorData++;
                }
        }
+
        *(cursorData++)=0;
        *(cursorData++)=*(cursorPix);
-       *dataSize=(int)((long int)cursorData-(long int)data); //Note: casted to long for portability with 64 bits architectures
+       *dataSize=(int)((long int)cursorData-(long int)data)-2; /* Note: casted to long for portability with 64 bits architectures */
 }
 
-//Expands an array into an image
-int mExpandGraphic(unsigned char* array,tImage *image, int virtualSize) {
-       /*
-               Reads array and extracts tImage
-               returns the next image address or -1 in case of error
+/***************************************************************\
+|               Main compress and expand graphics               |
+\***************************************************************/
 
+/*
                Header info:
-                char checksum, short int height, short int width, (char)0, char compressionType
-                normaly: (* ignored types)
-                checksum* - height - 00 - width - 00 - 00* - compression type
+                1 byte  - checksum           char checksum
+                2 bytes - height             short int height
+                2 bytes - width              short int width
+                1 byte  - 00                 (char)0
+                1 byte  - compression type   unsigned char compressionType
+*/
+
+/* Expands an array into an image */
+int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes) {
+       /*
+               Reads data and extracts tImage
+               returns the next image address or -1 in case of error
        */
 
-  int cursor=0;
-  int i=1;
-
-  //Get memory for the image
-       image->height=((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]) ;
-       i=i+2;
-       image->width =((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]);
-       i=i+2;
-       (*image).size  =(*image).height*(*image).width;
-       virtualSize=(((*image).height*((*image).width+((*image).width&1)))>>1);
-       i++;
-
-  switch ((unsigned char)array[i++]) {
-               case PG_COMP_RAW: //No Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               (*image).pix[cursor++]=array[i++];
-                       }
+       int imageSizeInBytes;
+       int result;
+
+       data++;
+       image->height=((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+       image->width =((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+
+       if (*(data++)) return -1; /* Verify format */
+       image->type=(unsigned char)(*(data++));
+       dataSizeInBytes-=7;
+
+       if (image->type&0xB0) {
+               image->widthInBytes=(image->width+1)/2;
+       } else {
+               image->widthInBytes=(image->width+7)/8;
+       }
+       imageSizeInBytes=image->widthInBytes*image->height;
+
+       switch (getAlgor(image->type)) {
+               case COMPRESS_RAW: /* No Compression Algorithm */
+                       if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+                       memcpy(image->pix,data,imageSizeInBytes);
+                       result=COMPRESS_RESULT_SUCCESS;
                        break;
-               case PG_COMP_RLE_LR: //RLE Left to Right Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(cursor++)]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[(cursor++)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_RLE_UD: //RLE Up to Down Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(transpose(cursor++,(*image).width,(*image).height))]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[transpose(cursor++,(*image).width,(*image).height)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_LR: //LZ Groody Up to Down Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       expandLzx(array,image,&i,cursor,virtualSize);
+               case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_UD: //LZ Groody Left to Right Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       {
-                       unsigned char* outputaux=getMemory(virtualSize);
-                       expandLzx(array,image,&i,cursor,virtualSize);
-                       //Transpose
-                 while (cursor<virtualSize) outputaux[transpose(cursor,(*image).width,(*image).height)]=(*image).pix[cursor++];
-                       free((*image).pix);
-                       (*image).pix=outputaux;
-                       }
+               case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
                default:
-                return -1;
+                       result=COMPRESS_RESULT_FATAL;
+                       break;
        }
-       return i;
+       return result; /* Ok */
 }
 
-#define COMPRESS_WORKING_ALGORITHMS 3
-
-//Compress an image into an array
-int mCompressGraphic(unsigned char* data,tImage* i, int* size) {
-       //Declare variables
+/* Compress an image into binary data */
+int mCompressGraphic(unsigned char* data,tImage* image, int* dataSizeInBytes) {
+       /* Declare variables */
+       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
        int            compressedSize [COMPRESS_WORKING_ALGORITHMS];
        int            algorithm;
-       int            cursor;
-       int            virtualsize;
-       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
-       unsigned char* outputaux;
-
-       //Initialize variables
-       virtualsize=(((i->width)+1)>>1)*i->height;
-       outputaux=getMemory(virtualsize);
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) compressedSize[cursor]=virtualsize;
-       cursor=0;
-
-       //B0
-       compressed[0]=getMemory(compressedSize[0]);
-       memcpy(compressed[0],i->pix,compressedSize[0]);
-
-       //B1
-       compressed[1]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       compressRle(compressed[1],i,&(compressedSize[1]));
-
-       //B2
-       compressed[2]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       //Transpose
-  while (cursor<=virtualsize) {
-               outputaux[cursor]=i->pix[transpose(cursor,i->width,i->height)];
-               cursor++;
-       }
-       free(i->pix);
-       i->pix=outputaux;
-       compressRle(compressed[2],i,&(compressedSize[2]));
-
-       /*Process results*/
-
-       //Select the best compression (find minimum)
-       *size=compressedSize[0];
-       algorithm=0;
-       for (cursor=1;cursor<3;cursor++) {
-               if ((*size)>compressedSize[cursor]) {
-                       (*size)=compressedSize[cursor];
-                       algorithm=cursor;
+       int            i;
+       int            imageSizeInBytes;
+
+       /* Initialize variables */
+       imageSizeInBytes=image->widthInBytes*image->height;
+       for (i=0;i<COMPRESS_WORKING_ALGORITHMS;i++) compressedSize[i]=imageSizeInBytes;
+
+       /*
+               Perform all compressions
+       */
+
+       /* COMPRESS_RAW */
+       compressed[COMPRESS_RAW]=getMemory(compressedSize[COMPRESS_RAW]);
+       memcpy(compressed[COMPRESS_RAW],image->pix,compressedSize[COMPRESS_RAW]);
+
+       /* COMPRESS_RLE_LR */
+       compressed[COMPRESS_RLE_LR]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       compressRle(compressed[COMPRESS_RLE_LR],image,&(compressedSize[COMPRESS_RLE_LR]));
+
+       /* COMPRESS_RLE_UD */
+       compressed[COMPRESS_RLE_UD]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       antiTransposeImage(image,imageSizeInBytes);
+       compressRle(compressed[COMPRESS_RLE_UD],image,&(compressedSize[COMPRESS_RLE_UD]));
+
+       /*
+               Process results
+       */
+
+       /* Select the best compression (find minimum) */
+       *dataSizeInBytes=compressedSize[COMPRESS_RAW];
+       algorithm=COMPRESS_RAW;
+       for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+               if ((*dataSizeInBytes)>compressedSize[i]) {
+                       (*dataSizeInBytes)=compressedSize[i];
+                       algorithm=i;
                }
        }
 
-       //Copy the best algorithm in the compressed data
-       memcpy(data+6,compressed[algorithm],*size);
-       (*size)+=6;
-
-       //Write header
-       //(16 bits)height (Intel short int format)
-       data[0]=i->height;
-       data[1]=i->height>>8;
-       //(16 bits)width (Intel short int format)
-       data[2]=i->width;
-       data[3]=i->width>>8;
-       //(12 bits)000000001011+(4 bits)algorithm
-       data[4]=0;
-       data[5]=0xB0+algorithm;
+       /* Copy the best algorithm in the compressed data */
+       memcpy(data+6,compressed[algorithm],*dataSizeInBytes);
+       (*dataSizeInBytes)+=6;
 
-       //Free all compression attempts
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) free(compressed[cursor]);
+       /*
+               Write header
+       */
+
+       /* (16 bits)height (Intel short int format) */
+       data[0]=image->height;
+       data[1]=image->height>>8;
+       /* (16 bits)width (Intel short int format) */
+       data[2]=image->width;
+       data[3]=image->width>>8;
+       /* (8 bits)00000000+(4 bits)palette type+(4 bits)algorithm */
+       data[4]=0;
+       data[5]=image->type|algorithm;
 
+       /* Free all compression attempts */
+       for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
        return 1;
 }
index 10e34a16128c09ca11b945e5a2ba5aa3629d4296..8497f6fc64a6baeaa14a859627f916685ae4a55e 100644 (file)
 */
 
 /*
-compress.c: Princed Resources : Image Compressor
+compress.c: Princed Resources : Image Compression Library
 ¯¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 2.00 (2004-Mar-07)
 
  Note:
   DO NOT remove this copyright notice
@@ -39,71 +40,125 @@ compress.c: Princed Resources : Image Compressor
 #include <string.h>
 #include "compress.h"
 #include "memory.h"
-
-//reserved memory for the Lzx algorithm
-#define MAX_MOD_SIZE_IN_LZX 32001                     /* 38401 */
-//modulus to be used in the 10 bits of the algorithm
-#define MAX_MXD_SIZE_IN_LZX 0x400
+#include "pr.h"
 
 /***************************************************************\
-|                Compression algorithm handling                 |
+|                        Image transpose                        |
 \***************************************************************/
 
-//Determines where the transposed byte must be saved
-int transpose(int x,int n,int m) {
-       return ((x%m)*((n+1)/2))+(int)(x/m);
+/* Determines where the transposed byte must be saved */
+int transpose(int x,int w,int h) {
+       return ((x%h)*(w))+(int)(x/h);
+}
+
+void transposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[transpose(cursor,image->widthInBytes,image->height)]=image->pix[cursor];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
 }
 
-//B3 and B4 expansion algorithm sub function
+void antiTransposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[cursor]=image->pix[transpose(cursor,image->widthInBytes,image->height)];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
+}
+
+/***************************************************************\
+|                    Uncompression algorithms                   |
+\***************************************************************/
+
+/* LZG expansion algorithm sub function */
 unsigned char popBit(unsigned char *byte) {
-  unsigned char bit=(unsigned char)((*byte)&1);
-  (*byte)>>=1;
-  return bit;
+       unsigned char bit=(unsigned char)((*byte)&1);
+       (*byte)>>=1;
+       return bit;
 }
 
-//Expands B3/B4 algorithm
-void expandLzx(unsigned /* note: if error remove signed */char* array,tImage* img, int *i,int cursor, int virtualSize) {
+/* Expands LZ Groody algorithm. This is the core of PR */
+int expandLzg(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
        char k;
-       int pos,h;
+       int location,h,cursor=0,pos=0;
        unsigned char maskbyte,rep;
 
-       for(pos=0;pos<MAX_MXD_SIZE_IN_LZX;(*img).pix[pos]=0,pos++); //clean output garbage
-       while (cursor<virtualSize) {
-               maskbyte=array[*i];(*i)++;
-               for (k=8;k&&(cursor<virtualSize);k--) {
+       if ((image->pix=getMemory(/*imageSize*/MAX_MOD_SIZE_IN_LZG))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+       for(location=0;location<MAX_MOD_SIZE_IN_LZG;image->pix[location]=0,location++); /* clean output garbage */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               maskbyte=array[pos++];
+               for (k=8;k&&(cursor<imageSize);k--) {
                        if (popBit(&maskbyte)) {
-                               (*img).pix[cursor]=array[*i];(*i)++;cursor++;
+                               image->pix[cursor++]=array[pos++];
                        } else {
-                               pos=66+((0x100)*((rep=array[*i])&3))+(unsigned char)array[(*i)+1];(*i)+=2;
+                               location=66+(((rep=array[pos])&3)<<8)+(unsigned char)array[pos+1];pos+=2;
                                rep=(unsigned char)((rep>>2)+3);
-                               while (rep--) { //Be careful in big images
-                                       h=cursor/MAX_MXD_SIZE_IN_LZX-(pos%MAX_MXD_SIZE_IN_LZX>cursor%MAX_MXD_SIZE_IN_LZX);
-                                       (*img).pix[cursor]=(*img).pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZX+pos%MAX_MXD_SIZE_IN_LZX];cursor++;pos++;
+                               while (rep--) { /* Be careful in big images */
+                                       h=cursor/MAX_MXD_SIZE_IN_LZG-((location%MAX_MXD_SIZE_IN_LZG)>(cursor%MAX_MXD_SIZE_IN_LZG));
+                                       image->pix[cursor++]=image->pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZG+(location++)%MAX_MXD_SIZE_IN_LZG];
+
+//                                     h=((cursor-(location&0x3FF))&(~0x3FF));
+//                                     image->pix[cursor]=image->pix[((h<0)?0:h)+(location&0x3FF)];
+       //                              cursor++;location++;
                                }
                        }
                }
        }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
+}
+
+/* Expands RLE algorithm */
+int expandRle(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
+       int cursor=0;
+       register signed char rep;
+       int pos=0;
+
+       if ((image->pix=getMemory(imageSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               rep=(signed char)(array[pos++]);
+               if (rep<0) {
+                       /* Negative */
+                       while (rep++) image->pix[cursor++]=array[pos];
+                       pos++;
+               } else {
+                       /* Positive */
+                       rep=~rep;
+                       while (rep++) image->pix[cursor++]=array[pos++];
+               }
+       }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
 }
 
-//Compress B1/B2 algorithm
+/***************************************************************\
+|                    Compression algorithms                     |
+\***************************************************************/
+
+/* Compress using the Run Length Encoding algorithm */
 void compressRle(unsigned char* data,tImage* img,int *dataSize) {
-       //Declare pointers
+       /* Declare pointers */
        unsigned char* cursorData  = data;
        char*          counter;
-       unsigned char* cursorPix   = (*img).pix;
-       unsigned char* imgEnd      = (*img).pix+(*dataSize);
+       unsigned char* cursorPix   = img->pix;
+       unsigned char* imgEnd      = img->pix+(*dataSize);
 
        while (cursorPix<imgEnd) {
-               //Step 1: Create counter
+               /* Step 1: Create counter */
                *(counter=(char*)(cursorData++))=-1;
 
-               //Step 2: Look and copy the string until a repeated byte is found
+               /* Step 2: Look and copy the string until a repeated byte is found */
                while (
                        (cursorPix<imgEnd)&&
                        (
                                (*cursorPix!=*(cursorPix+1))||
                                (
-                                       (*cursorPix==*(cursorPix+1))&&
+                                       /*(*cursorPix==*(cursorPix+1))&&*/
                                        ((cursorPix+1)<imgEnd)&&
                                        (*cursorPix!=*(cursorPix+2))
                                )
@@ -116,169 +171,154 @@ void compressRle(unsigned char* data,tImage* img,int *dataSize) {
                        cursorData++;
                }
 
-               //Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions
+               /* Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions */
                if (*counter==-1) {
-                       while ((cursorPix<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
+                       while ((cursorPix+1<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
                                cursorPix++;
                                (*counter)--;
                        }
 
-                       *(cursorData)=*(cursorPix); //Print repeated char
+                       *(cursorData)=*(cursorPix); /* Print repeated char */
                        cursorPix++;
                        cursorData++;
                }
        }
+
        *(cursorData++)=0;
        *(cursorData++)=*(cursorPix);
-       *dataSize=(int)((long int)cursorData-(long int)data); //Note: casted to long for portability with 64 bits architectures
+       *dataSize=(int)((long int)cursorData-(long int)data)-2; /* Note: casted to long for portability with 64 bits architectures */
 }
 
-//Expands an array into an image
-int mExpandGraphic(unsigned char* array,tImage *image, int virtualSize) {
-       /*
-               Reads array and extracts tImage
-               returns the next image address or -1 in case of error
+/***************************************************************\
+|               Main compress and expand graphics               |
+\***************************************************************/
 
+/*
                Header info:
-                char checksum, short int height, short int width, (char)0, char compressionType
-                normaly: (* ignored types)
-                checksum* - height - 00 - width - 00 - 00* - compression type
+                1 byte  - checksum           char checksum
+                2 bytes - height             short int height
+                2 bytes - width              short int width
+                1 byte  - 00                 (char)0
+                1 byte  - compression type   unsigned char compressionType
+*/
+
+/* Expands an array into an image */
+int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes) {
+       /*
+               Reads data and extracts tImage
+               returns the next image address or -1 in case of error
        */
 
-  int cursor=0;
-  int i=1;
-
-  //Get memory for the image
-       image->height=((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]) ;
-       i=i+2;
-       image->width =((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]);
-       i=i+2;
-       (*image).size  =(*image).height*(*image).width;
-       virtualSize=(((*image).height*((*image).width+((*image).width&1)))>>1);
-       i++;
-
-  switch ((unsigned char)array[i++]) {
-               case PG_COMP_RAW: //No Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               (*image).pix[cursor++]=array[i++];
-                       }
+       int imageSizeInBytes;
+       int result;
+
+       data++;
+       image->height=((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+       image->width =((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+
+       if (*(data++)) return -1; /* Verify format */
+       image->type=(unsigned char)(*(data++));
+       dataSizeInBytes-=7;
+
+       if (image->type&0xB0) {
+               image->widthInBytes=(image->width+1)/2;
+       } else {
+               image->widthInBytes=(image->width+7)/8;
+       }
+       imageSizeInBytes=image->widthInBytes*image->height;
+
+       switch (getAlgor(image->type)) {
+               case COMPRESS_RAW: /* No Compression Algorithm */
+                       if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+                       memcpy(image->pix,data,imageSizeInBytes);
+                       result=COMPRESS_RESULT_SUCCESS;
                        break;
-               case PG_COMP_RLE_LR: //RLE Left to Right Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(cursor++)]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[(cursor++)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_RLE_UD: //RLE Up to Down Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(transpose(cursor++,(*image).width,(*image).height))]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[transpose(cursor++,(*image).width,(*image).height)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_LR: //LZ Groody Up to Down Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       expandLzx(array,image,&i,cursor,virtualSize);
+               case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_UD: //LZ Groody Left to Right Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       {
-                       unsigned char* outputaux=getMemory(virtualSize);
-                       expandLzx(array,image,&i,cursor,virtualSize);
-                       //Transpose
-                 while (cursor<virtualSize) outputaux[transpose(cursor,(*image).width,(*image).height)]=(*image).pix[cursor++];
-                       free((*image).pix);
-                       (*image).pix=outputaux;
-                       }
+               case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
                default:
-                return -1;
+                       result=COMPRESS_RESULT_FATAL;
+                       break;
        }
-       return i;
+       return result; /* Ok */
 }
 
-#define COMPRESS_WORKING_ALGORITHMS 3
-
-//Compress an image into an array
-int mCompressGraphic(unsigned char* data,tImage* i, int* size) {
-       //Declare variables
+/* Compress an image into binary data */
+int mCompressGraphic(unsigned char* data,tImage* image, int* dataSizeInBytes) {
+       /* Declare variables */
+       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
        int            compressedSize [COMPRESS_WORKING_ALGORITHMS];
        int            algorithm;
-       int            cursor;
-       int            virtualsize;
-       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
-       unsigned char* outputaux;
-
-       //Initialize variables
-       virtualsize=(((i->width)+1)>>1)*i->height;
-       outputaux=getMemory(virtualsize);
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) compressedSize[cursor]=virtualsize;
-       cursor=0;
-
-       //B0
-       compressed[0]=getMemory(compressedSize[0]);
-       memcpy(compressed[0],i->pix,compressedSize[0]);
-
-       //B1
-       compressed[1]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       compressRle(compressed[1],i,&(compressedSize[1]));
-
-       //B2
-       compressed[2]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       //Transpose
-  while (cursor<=virtualsize) {
-               outputaux[cursor]=i->pix[transpose(cursor,i->width,i->height)];
-               cursor++;
-       }
-       free(i->pix);
-       i->pix=outputaux;
-       compressRle(compressed[2],i,&(compressedSize[2]));
-
-       /*Process results*/
-
-       //Select the best compression (find minimum)
-       *size=compressedSize[0];
-       algorithm=0;
-       for (cursor=1;cursor<3;cursor++) {
-               if ((*size)>compressedSize[cursor]) {
-                       (*size)=compressedSize[cursor];
-                       algorithm=cursor;
+       int            i;
+       int            imageSizeInBytes;
+
+       /* Initialize variables */
+       imageSizeInBytes=image->widthInBytes*image->height;
+       for (i=0;i<COMPRESS_WORKING_ALGORITHMS;i++) compressedSize[i]=imageSizeInBytes;
+
+       /*
+               Perform all compressions
+       */
+
+       /* COMPRESS_RAW */
+       compressed[COMPRESS_RAW]=getMemory(compressedSize[COMPRESS_RAW]);
+       memcpy(compressed[COMPRESS_RAW],image->pix,compressedSize[COMPRESS_RAW]);
+
+       /* COMPRESS_RLE_LR */
+       compressed[COMPRESS_RLE_LR]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       compressRle(compressed[COMPRESS_RLE_LR],image,&(compressedSize[COMPRESS_RLE_LR]));
+
+       /* COMPRESS_RLE_UD */
+       compressed[COMPRESS_RLE_UD]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       antiTransposeImage(image,imageSizeInBytes);
+       compressRle(compressed[COMPRESS_RLE_UD],image,&(compressedSize[COMPRESS_RLE_UD]));
+
+       /*
+               Process results
+       */
+
+       /* Select the best compression (find minimum) */
+       *dataSizeInBytes=compressedSize[COMPRESS_RAW];
+       algorithm=COMPRESS_RAW;
+       for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+               if ((*dataSizeInBytes)>compressedSize[i]) {
+                       (*dataSizeInBytes)=compressedSize[i];
+                       algorithm=i;
                }
        }
 
-       //Copy the best algorithm in the compressed data
-       memcpy(data+6,compressed[algorithm],*size);
-       (*size)+=6;
-
-       //Write header
-       //(16 bits)height (Intel short int format)
-       data[0]=i->height;
-       data[1]=i->height>>8;
-       //(16 bits)width (Intel short int format)
-       data[2]=i->width;
-       data[3]=i->width>>8;
-       //(12 bits)000000001011+(4 bits)algorithm
-       data[4]=0;
-       data[5]=0xB0+algorithm;
+       /* Copy the best algorithm in the compressed data */
+       memcpy(data+6,compressed[algorithm],*dataSizeInBytes);
+       (*dataSizeInBytes)+=6;
 
-       //Free all compression attempts
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) free(compressed[cursor]);
+       /*
+               Write header
+       */
+
+       /* (16 bits)height (Intel short int format) */
+       data[0]=image->height;
+       data[1]=image->height>>8;
+       /* (16 bits)width (Intel short int format) */
+       data[2]=image->width;
+       data[3]=image->width>>8;
+       /* (8 bits)00000000+(4 bits)palette type+(4 bits)algorithm */
+       data[4]=0;
+       data[5]=image->type|algorithm;
 
+       /* Free all compression attempts */
+       for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
        return 1;
 }
index c1bcd91823183f71516380ec6fcb1a8933845429..a49cd3418168bec6b367ee5e885e1889e596eafc 100644 (file)
@@ -35,38 +35,42 @@ resources.c: Princed Resources : Resource Handler
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
 
-//Includes
+/* Includes */
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include "pr.h"
-#include "xml.h"
+#include "xmlparse.h"
 #include "xmlsearch.h"
 #include "disk.h"
 #include "memory.h"
 #include "resources.h"
 #include "compress.h"
 
+extern FILE* outputStream;
+
 /***************************************************************\
-|                       File format handling                    |
+|                       Item Type Detector                      |
 \***************************************************************/
 
-int verifyLevelHeader(unsigned char* array, int size) {
+int verifyLevelHeader(const unsigned char *array, int size) {
        return (((size==2306)||(size==2305))&&!(array[1698]&0x0F)&&!(array[1700]&0x0F)&&!(array[1702]&0x0F));
 }
 
-int verifyImageHeader(unsigned char* array, int size) {
-       //return (size>6) && (!(((!array[1])||(array[2])||(!array[3])||(array[4])||(array[5])||(((unsigned char)array[6]&0xF0)!=0xB0))));
-       return (size>7) && (!array[5]) && (((unsigned char)array[6]&0xF0)==0xB0);
-       //TODO: fix the expression
+int verifyImageHeader(const unsigned char *array, int size) {
+       unsigned char imageBitRate;
+       imageBitRate=((unsigned char)array[6]&0xF0);
+       return (size>7) && (!array[5]) && ((imageBitRate==0xB0));
+       /* return (size>7) && (!array[5]) && ((imageBitRate==0xB0)||(imageBitRate==0x00)); */
 }
 
-int verifyPaletteHeader(unsigned char* array, int size) {
+int verifyPaletteHeader(const unsigned char *array, int size) {
        return ((size==101)&&(!array[2])&&(!array[3])&&(array[4]==0x10));
 }
 
-int verifyMidiHeader(unsigned char* array, int size) {
+int verifyMidiHeader(const unsigned char *array, int size) {
        return
-         (size>6) &&
+               (size>6) &&
                (array[1]==0x02) &&
                (array[2]=='M') &&
                (array[3]=='T') &&
@@ -75,26 +79,26 @@ int verifyMidiHeader(unsigned char* array, int size) {
        ;
 }
 
-int verifyWaveHeader(unsigned char* array, int size) {
+int verifyWaveHeader(const unsigned char *array, int size) {
        return
                (size>1)&&(array[1]==0x01)
        ;
 }
 
-int verifySpeakerHeader(unsigned char* array, int size) {
+int verifySpeakerHeader(const unsigned char *array, int size) {
        return
                (size>2)&&(array[1]==0x00) /* &&!(size%3) */
        ;
 }
 
-int verifyHeader(unsigned char* array, int size) {
-       if (verifyLevelHeader(array,size)) return 1;
-       if (verifyMidiHeader(array,size)) return 4;
-       if (verifyImageHeader(array,size)) return 2;
-       if (verifyPaletteHeader(array,size)) return 6;
-       if (verifyWaveHeader(array,size)) return 3;
-       if (verifySpeakerHeader(array,size)) return 7;
-       return 05;
+int verifyHeader(const unsigned char *array, int size) {
+       if (verifyLevelHeader  (array,size)) return RES_TYPE_LEVEL;
+       if (verifyMidiHeader   (array,size)) return RES_TYPE_MIDI;
+       if (verifyImageHeader  (array,size)) return RES_TYPE_IMAGE;
+       if (verifyPaletteHeader(array,size)) return RES_TYPE_PALETTE;
+       if (verifyWaveHeader   (array,size)) return RES_TYPE_WAVE;
+       if (verifySpeakerHeader(array,size)) return RES_TYPE_PCSPEAKER;
+       return RES_TYPE_BINARY;
 }
 
 const char* getExtDesc(int type) {
@@ -103,105 +107,237 @@ const char* getExtDesc(int type) {
 }
 
 /***************************************************************\
-|                      Parsing resource file                    |
+|                Partial Resource List Functions                |
+\***************************************************************/
+
+static tResIdList partialList;
+
+void parseGivenPath(char* path) {
+       /*
+               PRE:  partialList.list was not allocated
+               POST:
+                partialList.count=0 and partialList.list=NULL if all resources
+                path was trimed in the "@"
+       */
+
+       int i;
+       int separator=0;
+       int resourceValue;
+       int j=0;
+       unsigned char n;
+
+       /* Check if the variable wasn't initialized before */
+       if (partialList.count!=0) return;
+       partialList.list=NULL;
+
+       /* Validates the NULL path */
+       if (path==NULL) return;
+
+       /* Locate the string separation */
+       while (path[separator]&&path[separator]!='@') separator++;
+
+       /* If no separation */
+       if (!path[separator]) return; /* There was no separator */
+
+       /* Count values, separate them with '\0' and alloc memory */
+       partialList.count=1;
+       path[separator]=0; /* Trim the path to the separator */
+       i=++separator;
+       while(path[i]) {
+               if (path[i]==',') {
+                       partialList.count++;
+                       path[i]=0;
+               }
+               i++;
+       }
+       partialList.list=(tResIdListItem*)malloc(sizeof(tResIdListItem)*partialList.count);
+
+       /* Parse values and save them in the list */
+       resourceValue=0;
+       for(i=separator;j!=partialList.count;i++) {
+               n=path[i];
+               if ((0x2F<n)&&(n<0x3A)) {
+                       resourceValue=resourceValue*10+(n-'0');
+               } else {
+                       if (n) {
+                               partialList.list[j].idType=eString;
+                               partialList.list[j].value=(char*)strallocandcopy(repairFolders(path+separator));
+                               while (path[i]) i++;
+                       } else {
+                               partialList.list[j].idType=eValue;
+                               partialList.list[j].value=(void*)resourceValue;
+                       }
+                       resourceValue=0;
+                       separator=i+1;
+                       j++;
+               }
+       }
+}
+
+int isInThePartialList(const char* vFile, int value) {
+       /*
+               Cases:
+                       "path/path@"                    all files are false
+                       "path/path"                     all files are true
+                       "path/path@12file/jjj.bmp,777"  only file "12file/jjj.bmp" and id 777 are true
+                       "path/path@1,2,3"               only ids 1, 2 and 3 are true
+       */
+       int i;
+       char* file;
+
+       if (!partialList.count) return 1;
+       file=(char*)repairFolders(vFile);
+
+       for (i=0;i<partialList.count;i++) {
+               if (partialList.list[i].idType==eValue) {
+                       if (value==(int)partialList.list[i].value) return 1;
+               } else {
+                       if (file)
+                               if (equalsIgnoreCase(file,(char*)partialList.list[i].value)) return 1;
+               }
+       }
+       return 0;
+}
+
+void freePartialList() {
+       int i;
+       for (i=0;i<partialList.count;i++) {
+               if (partialList.list[i].idType==eString)
+                       free(partialList.list[i].value);
+       }
+       partialList.count=0;
+}
+
+/***************************************************************\
+|                       Checksum handling                       |
+\***************************************************************/
+
+int checkSum(unsigned char* data,int size) {
+       unsigned char  checksum = 1;
+
+       /* calculates the checksum */
+       while (size--) checksum+=*(data++);
+       return !checksum;
+}
+
+/***************************************************************\
+|                     Parsing resource file                     |
 \***************************************************************/
 
-//Initializes the resource table
+/* Initializes the resource table */
 void emptyTable(tResource* r[]) {
        int i=MAX_RES_COUNT;
        while (i--) *(r++)=NULL;
 }
 
-//TODO: use a static XML tree and two functions: parseFile and freeXmlStructure
-
-//Resources input xml tree. Private+abstract variable
+/* Resources input xml tree. Private+abstract variable */
 static tTag* xmlStructure=NULL; /* Keeping the parsed file structure in memory will save a lot of time */
 
-
-//parse file
-char parseFile(const char* vFile, const char* datFile, tResource* r[]) {
-       //Declare error variable
+int parseStructure(const char* vFile) {
+       static const char defaultXmlFile[]=RES_XML_RESOURC_XML;
        int error=0;
 
-       //Generate xml structure if doesn't exist
-       if (xmlStructure==NULL) xmlStructure=parseXmlFile(vFile,&error);
-       if (error) {
-               xmlStructure=NULL;
-               return error;
+       /* Generate xml structure if doesn't exist */
+       if (xmlStructure==NULL) {
+               /* Set default values */
+               if (vFile==NULL) vFile=defaultXmlFile;
+               xmlStructure=parseXmlFile(vFile,&error);
        }
+       if (error) xmlStructure=NULL;
+       return error;
+}
+
+/* parse file */
+int parseFile(const char* vFile, const char* datFile, tResource* r[]) {
+       /* Declare error variable */
+       int error;
+       tPassWork pass;
 
-       //Use the xml structure to Generate the resource structure of the file
+       /* Generate xml structure if doesn't exist */
+       if ((error=(parseStructure(vFile)))) return error;
+
+       /* Use the xml structure to Generate the resource structure of the file */
        emptyTable(r);
-       workTree(xmlStructure,datFile,r);
+       pass.datFile=datFile;
+       pass.r=r;
+       workTree(xmlStructure,&pass,workTag);
 
-       //All done
+       /* All done */
        return 0;
 }
 
 void freeParsedStructure() {
-       //Free if exist
+       /* Free if exist */
        if (xmlStructure!=NULL) freeTagStructure(xmlStructure);
-
-       //Reinitializes the veriable
+       /* Reinitializes the variable */
        xmlStructure=NULL;
-
-       return;
 }
 
+/***************************************************************\
+|                     Unknown.xml primitives                    |
+\***************************************************************/
 
-//Resources output to xml functions. Private+abstract variable
+/* Resources output to xml functions. Private+abstract variable */
 static FILE* unknownXmlFile=NULL;
 
-void AddToUnknownXml(const char* vFiledat,unsigned short id,const char* ext,char type,const char* vDirExt,unsigned short pal) {
-       //Open file if not open
+void AddToUnknownXml(const char* vFiledatWithPath,unsigned short id,const char* ext,char type,const char* vDirExt,unsigned short pal,const char* vFiledat,int optionflag,int count) {
+       /* Open file if not open */
        if (unknownXmlFile==NULL) {
                char xmlFile[MAX_FILENAME_SIZE];
-               sprintf(xmlFile,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_XML,vDirExt,vFiledat);
+               sprintf(xmlFile,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_XML,vDirExt,vFiledatWithPath);
 
-               //Open file
-               if (!writeOpen(xmlFile,&unknownXmlFile)) return;
+               /* Open file */
+               if (!writeOpen(xmlFile,&unknownXmlFile,optionflag)) return;
 
-               //Save headers
+               /* Save headers */
                if (type==6) pal=id;
                fprintf(unknownXmlFile,RES_XML_UNKNOWN_START,
-                       vFiledat,vFiledat,pal
+                       vFiledat,vFiledatWithPath,pal
                );
        }
 
-       //Write item
+       /* Write item */
        fprintf(unknownXmlFile,RES_XML_UNKNOWN_ITEM,
-               id,id,ext,getExtDesc(type),id
-       ); //To the xml output
+               id,getExtDesc(type),count,ext,getExtDesc(type),getExtDesc(type),count
+       ); /* To the xml output */
 }
 
-void endUnknownXml() {
+static unsigned int typeCount[RES_TYPECOUNT]; /* initialized in 0 */
+
+void endUnknownXml(int optionflag, const char* backupExtension) {
        if (unknownXmlFile!=NULL) {
+               int i;
                fprintf(unknownXmlFile,RES_XML_UNKNOWN_END);
-               fclose(unknownXmlFile);
+               writeCloseOk(unknownXmlFile,optionflag,backupExtension);
                unknownXmlFile=NULL;
+               for (i=0;i<RES_TYPECOUNT;i++) typeCount[i]=0;
        }
 }
 
-//Resources extra functions
-void getFileName(char* vFileext,const char* vDirExt,tResource* r,short id,const char* vFiledat, const char* vDatFileName) {
-       static const char extarray[8][4]=RES_FILE_EXTENSIONS;
-       const char* ext;
+/***************************************************************\
+|                   Resources extra functions                   |
+\***************************************************************/
+
+void getFileName(char* vFileext,const char* vDirExt,tResource* r,unsigned short id,const char* vFiledat, const char* vDatFileName,int optionflag, const char* backupExtension) {
+       static const char* extarray[]=RES_FILE_EXTENSIONS;
+       int pos;
 
        if (r->path==NULL) {
-               ext=extarray[((r->type<=7)&&(r->type>=0))?r->type:5];
-               //set filename
-               sprintf(vFileext,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_FILES,vDirExt,vDatFileName,id,ext);
-               AddToUnknownXml(vDatFileName,id,ext,r->type,vDirExt,r->palette);
+               pos=((r->type<RES_TYPECOUNT)&&(r->type>=0))?r->type:RES_TYPE_BINARY;
+               typeCount[pos]++;
+
+               /* set filename */
+               sprintf(vFileext,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_FILES,vDirExt,vDatFileName,getExtDesc(pos),typeCount[pos],extarray[pos]);
+               AddToUnknownXml(vDatFileName,id,extarray[pos],r->type,vDirExt,r->palette,vFiledat,optionflag,typeCount[pos]);
        } else {
-               //set filename
+               /* set filename */
                sprintf(vFileext,"%s/%s",vDirExt,r->path);
        }
 }
 
-//Search files for the Import feature
-int importDir(const char* directory, const char* vResFile, int* pOption, const char* backupExtension,const char* vDatDirectory, FILE* output) {
-       //TODO send to a function called by parseFile & importDir
-       //Declare error variable
+/* Search files for the Import feature */
+int importDir(const char* directory, const char* vResFile, int pOption, const char* backupExtension,const char* vDatDirectory, FILE* output) {
+       /* Declare error variable */
        int error=0;
        char* datfile;
        char* recursive;
@@ -209,34 +345,95 @@ int importDir(const char* directory, const char* vResFile, int* pOption, const c
        int sizeOfFile;
        int result;
 
-       //Generate xml structure if doesn't exist
-       if (xmlStructure==NULL) xmlStructure=parseXmlFile(vResFile,&error);
-       if (error) {
-               xmlStructure=NULL;
-               return error;
-       }
+       /* Generate xml structure if doesn't exist */
+       if ((error=(parseStructure(vResFile)))) return error;
 
-       //Use the xml structure to Generate the file list
-       getFiles(xmlStructure);
+       /* Use the xml structure to Generate the file list */
+       workTree(xmlStructure,NULL,addFileToList);
 
        while(datfile=getFileFromList()) {
                sizeOfPath=strlen(vDatDirectory);
                sizeOfFile=strlen(datfile);
 
-               //Generate full vDatDirectory/datfile path
-               recursive=getMemory(sizeOfPath+1+sizeOfFile);
+               /* Generate full vDatDirectory/datfile path */
+               recursive=(char*)malloc(sizeOfPath+sizeOfFile+2);
                memcpy(recursive,vDatDirectory,sizeOfPath);
                recursive[sizeOfPath]=DIR_SEPARATOR;
                memcpy(recursive+sizeOfPath+1,datfile,sizeOfFile+1);
 
-               //Run program
+               /* Run program */
                result=prMain(pOption, backupExtension,directory,vResFile,recursive,datfile,NULL,output);
-               //Free mem
+               /* Free memory */
                free(datfile);
                free(recursive);
        }
 
-       //All done
+       /* All done */
        return result;
 }
 
+int isntADatFile(const char* testFile, const char* vResFile) {
+       /*
+               Results:
+                       0  Is a dat file
+                       1  It isn't a dat file
+                       -1 Parse error
+                       -2 No memory
+                       -3 Attribute not recognized
+                       -4 File not found
+       */
+
+       /* Declare result variable */
+       int result;
+       char* gottenFile;
+
+       /* Generate xml structure if doesn't exist */
+       if ((result=(parseStructure(vResFile)))) return result;
+
+       /* Use the xml structure to Generate the file list */
+       workTree(xmlStructure,NULL,addFileToList);
+       while((gottenFile=(getFileFromList()))) {
+               result=result||equalsIgnoreCase(gottenFile,testFile);
+               free(gottenFile);
+       }
+
+       /* All done */
+       return !result;
+}
+
+/***************************************************************\
+|                Resource tree browsing for DLL                 |
+\***************************************************************/
+
+#ifdef DLL
+
+tTag* resourceTreeGetRoot () {
+       return xmlStructure;
+}
+
+tTag* resourceTreeGetNext (tTag* whereAmI) {
+       return whereAmI->next;
+}
+
+tTag* resourceTreeGetChild(tTag* whereAmI) {
+       return whereAmI->child;
+}
+
+int   resourceTreeGetInfo (tTag* whereAmI,     char** tag, char** desc, char** path, char** file, char** itemtype, char** name, char** palette, char** type, char** value, char** version, char** number) {
+       if (whereAmI==NULL) return 0;
+       *tag=whereAmI->tag;
+       *desc=whereAmI->desc;
+       *path=whereAmI->path;
+       *file=whereAmI->file;
+       *itemtype=whereAmI->itemtype;
+       *name=whereAmI->name;
+       *palette=whereAmI->palette;
+       *type=whereAmI->type;
+       *value=whereAmI->value;
+       *version=whereAmI->version;
+       *number=whereAmI->number;
+       return 1;
+}
+
+#endif
+
index f26052d0688b4c0b64ee845fc6735a44e7bb41e3..8097f1113d0f0b2ab63ef6b3199718decd53708e 100644 (file)
@@ -29,42 +29,49 @@ disk.c: Princed Resources : Disk Access & File handling functions
 
   Modified by: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.10 (2003-Dec-03)
+  Modified by: Santiago Zamora <drkzight@users.sourceforge.net>
+  Version: 1.20 (2004-Jan-06)
 
  Note:
   DO NOT remove this copyright notice
 */
 
-//Defines
+/* Defines */
 #include "memory.h"
 #include <string.h>
 #include "pr.h"
 #include "disk.h"
-#include "xml.h" /* equalsIgnoreCase */
+#include "xmlparse.h" /* equalsIgnoreCase */
 
 #include <sys/types.h>
 #include <sys/stat.h>
-
+extern FILE* outputStream;
 #ifdef UNIX
        #define defmkdir(a) mkdir (a,(mode_t)0755)
        #include <dirent.h>
+       #include <termios.h>
+       //#include <curses.h>
+       #include <unistd.h>
+       #include <fcntl.h>
+       #define osIndepGetCharacter() getchar()
 #else
        #include <direct.h>
        #include "direntwin.h"
        #define defmkdir(a) mkdir (a)
+       #include <conio.h>
+       #define osIndepGetCharacter() getche()
 #endif
 
-#define isDirSep(a,i) ((a[i]=='\\')||(a[i]=='/'))
-
 /***************************************************************\
 |              Disk Access & File handling functions            |
 \***************************************************************/
 
-//Repair folders
+/* Repair folders */
 const char *repairFolders(const char* a) {
        int i,k;
-       static char result[260];
+       static char result[MAX_FILENAME_SIZE];
 
-       for (i=0,k=0;a[i]&&(k<260);) {
+       for (i=0,k=0;a[i]&&(k<MAX_FILENAME_SIZE);) {
                if (isDirSep(a,i)) {
                        result[k]=DIR_SEPARATOR;
                        i++;
@@ -80,41 +87,138 @@ const char *repairFolders(const char* a) {
 }
 
 
-//Create base directory of a file
+/* Create base directory of a file */
 int makebase(const char* p) {
        /*
                Creates the base directory of the given file "p"
                Returns 0 if created
                Returns -1 if an error occurred
 
-               Note: if the base dir already exists it will return -1!
+               Note: if the base directory already exists it will return -1!
        */
 
-       //Declare variables
-       int i,a;
+       /* Declare variables */
+       static char old[MAX_FILENAME_SIZE];
+       int i,a,equal=1;
        int size;
        char* aux;
 
-       //Initialize variables
-       aux=(char*)malloc(size=(strlen(p)+1));
-       memset(aux,0,size);
+       /* Initialize variables */
+       size=(strlen(p)+1);
+       aux=(char*)malloc(size);
 
-       //Make directories
+       /* Make directories */
        for (i=0;i<size;i++) {
-               if (p[i]==DIR_SEPARATOR) a=defmkdir(aux);
+               aux[i]=0;
+               equal=equal&&(old[i]==p[i]);
+               if ((!equal)&&(p[i]==DIR_SEPARATOR)) a=defmkdir(aux);
+               old[i]=p[i];
                aux[i]=p[i];
        }
-       free(aux);
 
+       free(aux);
        return a;
 }
 
-char writeOpen(const char* vFileext, FILE* *fp) {
+static tOpenFiles* openFilesList=NULL;
+
+void addFileToOpenFilesList(const char* fileName,int hasBackup) {
+       /*
+               Add a recently safe open file to the file pointer dynamic table
+               using the LIFO philosophy.
+       */
+
+       tOpenFiles* newNode;
+
+       /* Create the new node and fill in the fields */
+       newNode=(tOpenFiles*)malloc(sizeof(tOpenFiles));
+       newNode->next=openFilesList;
+       newNode->name=strallocandcopy(fileName);
+       if (hasBackup) {
+               newNode->size=mLoadFileArray(fileName,&(newNode->content));
+       } else {
+               newNode->size=0;
+       }
+       openFilesList=newNode;
+}
+
+void addPointerToOpenFilesList(FILE* fp) { /* TODO: use a define */
+       openFilesList->file=fp;
+}
+
+int getFromOpenFilesList(FILE* fp, char** fileName, unsigned char** content, unsigned long int *size) {
+       tOpenFiles* currentNode;
+       tOpenFiles* priorNode=NULL;
+
+       /* Search using FILE* file as key */
+       if (openFilesList==NULL) return 0; /* Empty list */
+       currentNode=openFilesList;
+       while ((currentNode->file!=fp)&&(currentNode->next!=NULL)) {
+               priorNode=currentNode;
+               currentNode=currentNode->next;
+       }
+       if (currentNode->file!=fp) return 0; /* Not found */
+
+       /* Return results */
+       *fileName=currentNode->name;
+       *content=currentNode->content;
+       *size=currentNode->size;
+
+       /* free node and set prior pointer to the next */
+       if (priorNode==NULL) {
+               openFilesList=currentNode->next;
+       } else {
+               priorNode->next=currentNode->next;
+       }
+       free(currentNode);
+
+       return 1;
+}
+
+int writeClose(FILE* fp,int dontSave,int optionflag,const char* backupExtension) {
+       unsigned char* content;
+       char* fileName;
+       unsigned long int size;
+
+       if (getFromOpenFilesList(fp,&fileName,&content,&size)) {
+               if (dontSave) {
+                       fclose(fp);
+                       if (size) {
+                               fp=fopen(fileName,"wb");
+                               if (fp==NULL) return -1;
+                               fwrite(content,1,size,fp);
+                       } else {
+                               remove(fileName);
+                       }
+               } else {
+                       /* File Existed before and we need to back it up */
+                       if (hasFlag(backup_flag)) {
+                               char aux[MAX_FILENAME_SIZE];
+                               static const char defaultbackupExtension[]=DEFAULT_BACKUP_EXTENSION;
+                               /* Set default values if there isn't */
+                               if (backupExtension==NULL) backupExtension=defaultbackupExtension;
+                               /* generate the file name */
+                               sprintf(aux,"%s.%s",fileName, backupExtension);
+                               fclose(fp);
+                               fp=fopen(aux,"wb");
+                               if (fp==NULL) return -2;
+                               fwrite(content,1,size,fp);
+                       }
+               }
+
+               free(fileName);
+               if (size) free(content);
+       }
+
+       return fclose(fp);
+}
+
+int writeOpen(const char* vFileext, FILE* *fp, int optionflag) {
        /*
                Opens vFileext for write access
-                if the path does't exist it is created
+                if the path doesn't exist it is created
                 if the file doesn't exist it is created
-                if the file does exist it is overwriten
+                if the file does exist it is overwritten
 
                Sets the file pointer and returns 1 if Ok or 0 if error
 
@@ -123,16 +227,63 @@ char writeOpen(const char* vFileext, FILE* *fp) {
                 1 if ok
        */
        const char* file;
+       whatIs fileType;
+       static int all=0;
+       int result;
+
+#ifdef UNIX
+#ifndef IGNORE_TERM_CHANGE
+       /* This will eliminate the enter after the input */
+       struct termios term;
+       struct termios termOld;
+
+       tcgetattr (STDIN_FILENO, &term);
+       tcgetattr (STDIN_FILENO, &termOld); /* save original proprieties */
+       term.c_lflag &= ~(ICANON);
+       tcsetattr (STDIN_FILENO, TCSANOW, &term);
+#endif
+#endif
 
-       //Create base dir and save file
+       /* Create base directory and save file */
        file=repairFolders(vFileext);
-       makebase(file);
 
-       return ((*fp=fopen(file,"wb"))!=NULL);
+       /* Verify if file already exists. */
+       fileType=isDir(vFileext);
+       if (fileType==eDirectory) return 0;
+
+       if (fileType==eFile) {
+               /* File exists. We need to ask */
+               if ((!(hasFlag(force_flag)))&&(!all)) {
+                       char answer;
+                       printf(PR_TEXT_DISK_REPLACE,getFileNameFromPath(file));
+                       answer=osIndepGetCharacter();
+                       printf("\n");
+                       if (charToUpper(answer)==PR_DISK_REPLACE_NO)  return 0;
+                       if (charToUpper(answer)==PR_DISK_REPLACE_ALL) all=1;
+               }
+       } else {
+               makebase(file);
+       }
+
+#ifdef UNIX
+#ifndef IGNORE_TERM_CHANGE
+       /* restoring previous terminal options */
+       term=termOld;
+       tcsetattr (STDIN_FILENO, TCSANOW, &termOld);
+#endif
+#endif
+       /*
+               If the file exists, we need to remember the old content in memory
+               if not, we need to know the name in case we need to delete it
+       */
+
+       addFileToOpenFilesList(file,hasFlag(backup_flag));
+       if ((result=((*fp=fopen(file,"wb"))!=NULL))) addPointerToOpenFilesList(*fp);
+       return result;
 }
 
 
-char writeData(const unsigned char* data, int ignoreChars, char* vFileext, int size) {
+int writeData(const unsigned char* data, int ignoreChars, char* vFileext, int size, int optionflag,const char* backupExtension) {
        /*
                Creates vFileext and saves data in it. In case the directory doesn't
                exist it will be created.
@@ -147,18 +298,18 @@ char writeData(const unsigned char* data, int ignoreChars, char* vFileext, int s
                 1 if ok
        */
 
-       //Declare variables
+       /* Declare variables */
        FILE* target;
        char  ok;
 
-       //Verify parameters
+       /* Verify parameters */
        size-=ignoreChars;
        if (size<=0) return 0;
 
-       //Save file
-       ok=writeOpen(vFileext,&target);
+       /* Save file */
+       ok=writeOpen(vFileext,&target,optionflag);
        ok=ok&&fwrite(data+ignoreChars,size,1,target);
-       ok=ok&&(!fclose(target));
+       ok=ok&&(!writeCloseOk(target,optionflag,backupExtension));
        return ok;
 }
 
@@ -169,23 +320,23 @@ int mLoadFileArray(const char* vFile,unsigned char** array) {
                In case the file couldn't be open or memory allocated returns 0.
        */
 
-       //declare variables
+       /* declare variables */
        FILE *fp;
        int  aux;
 
-       //Open the file
+       /* Open the file */
        if ((fp=fopen(repairFolders(vFile),"rb"))==NULL) {
                return 0;
        } else {
-               //get file size
+               /* get file size */
                fseek(fp,0,SEEK_END);
                aux=ftell(fp);
                if ( !aux || (aux>SIZE_OF_FILE) || ( ((*array=(unsigned char*)malloc(sizeof(char)*aux))==NULL) ) ) {
-                       //if the file was null or bigger than the max size or couldn't allocate the file in memory
+                       /* if the file was null or bigger than the max size or couldn't allocate the file in memory */
                        fclose(fp);
                        return 0;
                } else {
-                       //if the filewas succesfully open
+                       /* if the file was successfully open */
                        fseek(fp,0,SEEK_SET);
                        aux=fread (*array,1,aux,fp);
                        fclose(fp);
@@ -194,28 +345,8 @@ int mLoadFileArray(const char* vFile,unsigned char** array) {
        }
 }
 
-#define mSaveRaw(f,d,s) writeData(d,0,f,s)
-/*
-char mSaveRaw(const char* vFile,const unsigned char* output, int size) {
-       /*
-               Using the given string in vFile, it opens the file and saves the
-               first "size" bytes from the "output" in it.
-               In case the file couldn't be open or there was no size returns 0,
-               otherways returns 1.
-       /
-
-  FILE * pFile;
-
-       if (!size) return 0;
-  if (!writeOpen(vFile,&pFile)) return 0;
-
-  fwrite (output, 1, size, pFile);
-  fclose (pFile);
-  return 1;
-}
-*/
-
-char mDiskVealidateFileHeader(unsigned char* text, int size, FILE* fp) {
+#ifdef PR_FUTURE_CODE
+int mDiskVealidateFileHeader(unsigned char* text, int size, FILE* fp) {
        /*
                Validates if the file contains the following text in the stream.
                1 if it does
@@ -224,27 +355,28 @@ char mDiskVealidateFileHeader(unsigned char* text, int size, FILE* fp) {
                Moves the file pointer to the next position
        */
 
-       //Declare vars
+       /* Declare variables */
        int i;
        unsigned char* readText;
 
-       //Reserves memory to allocate the read bytes
+       /* Reserves memory to allocate the read bytes */
        readText=getMemory(size);
-       if (readText==NULL) return 0; //memory error, abort
+       if (readText==NULL) return 0; /* memory error, abort */
 
-       //Read the file and move the file pointer
+       /* Read the file and move the file pointer */
        if (!fread(readText,size,1,fp)) {
                free(readText);
                return 0;
        }
 
-       //Make the binary compare
+       /* Make the binary compare */
        for (i=0;(i<size)&&(readText[i]==text[i]);i++);
 
-       //Frees memory and returns the result
+       /* Frees memory and returns the result */
        free(readText);
-       return (i==size); //0 if the compare for was stopped before end reached
+       return (i==size); /* 0 if the compare for was stopped before end reached */
 }
+#endif
 
 const char* getFileNameFromPath(const char* path) {
        /*
@@ -264,8 +396,9 @@ const char* getFileNameFromPath(const char* path) {
 
 whatIs isDir(const char *path) {
        /*
-               1 if nombre is a directory
-               0 if nombre isn't a directory or doesn't exist
+               eDirectory if path is a directory
+               eNotFound if path isn't a directory or doesn't exist
+               eFile if it is a file
        */
        struct stat buf;
 
@@ -273,67 +406,72 @@ whatIs isDir(const char *path) {
        return (S_IFDIR&buf.st_mode)?eDirectory:eFile;
 }
 
-int recurseDirectory(const char* path,int* pOption, const char* extension,const char* dirName,const char* resFile, const char* datfilename,const char* datAuthor,FILE* output) {
+#ifndef IGNORERECURSIVEFUNCTIONS
+
+int recurseDirectory(const char* path,int optionflag, const char* extension,const char* dirName,const char* resFile, const char* datfilename,const char* datAuthor,FILE* output) {
        /*
-               Searchs for all .dat files in the directory
-               if recursive flag is set searchs over the dubdirectories
+               Search for all .dat files in the directory
+               if recursive flag is set search over the subdirectories
                if verbose flag is set shows some messages in the screen
                when .dat files are found it runs prMain form each of them
        */
 
-       //Declare variables
+       /* Declare variables */
        char*          recursive;
        struct dirent* directoryStructure;
        DIR*           dir;
 
-       //Opens directory
+       /* Opens directory */
        if ((dir = opendir(path))==NULL) {
                return 0;
        }
 
-       //Shows some messages
-       if ((optionflag&recursive_flag)&&(optionflag&verbose_flag)) { //Only recurse if recursive and verbose flags are set
-               printf("Processing '%s'...\n",path);
+       /* Shows some messages */
+       if ((hasFlag(recursive_flag))&&(hasFlag(verbose_flag))) { /* Only recourse if recursive and verbose flags are set */
+               fprintf(outputStream,PR_TEXT_DISK_PROCESSING,path);
        }
 
-       //Main cicle: while there are still more files left
+       /* Main loop: while there are still more files left */
        while ((directoryStructure = readdir(dir))!=NULL) {
                if /* Don't look over the system directories */
-                       (!(
-                               !strcmp(directoryStructure->d_name,".")||
-                               !strcmp(directoryStructure->d_name,"..")
-               )) {
-                       //Declare variables
+                       (
+                               strcmp(directoryStructure->d_name,".")&&
+                               strcmp(directoryStructure->d_name,"..")
+               ) {
+                       /* Declare variables */
                        int sizeOfPath=strlen(path);
                        int sizeOfFile=strlen(directoryStructure->d_name);
 
-                       //Generate recursive path
-                       recursive=getMemory(sizeOfPath+1+sizeOfFile);
+                       /* Generate recursive path */
+                       recursive=(char*)malloc(sizeOfPath+2+sizeOfFile);
                        memcpy(recursive,path,sizeOfPath);
                        recursive[sizeOfPath]=DIR_SEPARATOR;
                        memcpy(recursive+sizeOfPath+1,directoryStructure->d_name,sizeOfFile+1);
 
                        /*
-                               If recursive path is a directory and recursive flag is set recurse into it
+                               If recursive path is a directory and recursive flag is set recourse into it
                                if recursive path is a directory and recursive flag wasn't set, just ignore
                                if recursive path is not a directory and is a dat file, do prMain
                                if recursive path is not a directory and is not a dat file, ignore
                        */
                        if (isDir(recursive)==eDirectory) {
-                               if (optionflag&recursive_flag) { //Only recurse if recursive flag is set
-                                       recurseDirectory(recursive,pOption,extension,dirName,resFile,datfilename,datAuthor,output);
+                               if (hasFlag(recursive_flag)) { /* Only recourse if recursive flag is set */
+                                       recurseDirectory(recursive,optionflag,extension,dirName,resFile,datfilename,datAuthor,output);
                                }
                        } else {
                                char aux[]=".dat";
                                if (sizeOfFile>4) {
                                        if (equalsIgnoreCase(aux,directoryStructure->d_name+sizeOfFile-4)) {
-                                               prMain(pOption,extension,dirName,resFile,recursive,directoryStructure->d_name,datAuthor,output);
+                                               prMain(optionflag,extension,dirName,resFile,recursive,directoryStructure->d_name,datAuthor,output);
                                        }
                                }
                        }
-                       //Free all allocated mem
+                       /* Free all allocated memory */
                        free(recursive);
                }
        }
        return 1;
 }
+
+#endif
+
index c1bcd91823183f71516380ec6fcb1a8933845429..a49cd3418168bec6b367ee5e885e1889e596eafc 100644 (file)
@@ -35,38 +35,42 @@ resources.c: Princed Resources : Resource Handler
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
 
-//Includes
+/* Includes */
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include "pr.h"
-#include "xml.h"
+#include "xmlparse.h"
 #include "xmlsearch.h"
 #include "disk.h"
 #include "memory.h"
 #include "resources.h"
 #include "compress.h"
 
+extern FILE* outputStream;
+
 /***************************************************************\
-|                       File format handling                    |
+|                       Item Type Detector                      |
 \***************************************************************/
 
-int verifyLevelHeader(unsigned char* array, int size) {
+int verifyLevelHeader(const unsigned char *array, int size) {
        return (((size==2306)||(size==2305))&&!(array[1698]&0x0F)&&!(array[1700]&0x0F)&&!(array[1702]&0x0F));
 }
 
-int verifyImageHeader(unsigned char* array, int size) {
-       //return (size>6) && (!(((!array[1])||(array[2])||(!array[3])||(array[4])||(array[5])||(((unsigned char)array[6]&0xF0)!=0xB0))));
-       return (size>7) && (!array[5]) && (((unsigned char)array[6]&0xF0)==0xB0);
-       //TODO: fix the expression
+int verifyImageHeader(const unsigned char *array, int size) {
+       unsigned char imageBitRate;
+       imageBitRate=((unsigned char)array[6]&0xF0);
+       return (size>7) && (!array[5]) && ((imageBitRate==0xB0));
+       /* return (size>7) && (!array[5]) && ((imageBitRate==0xB0)||(imageBitRate==0x00)); */
 }
 
-int verifyPaletteHeader(unsigned char* array, int size) {
+int verifyPaletteHeader(const unsigned char *array, int size) {
        return ((size==101)&&(!array[2])&&(!array[3])&&(array[4]==0x10));
 }
 
-int verifyMidiHeader(unsigned char* array, int size) {
+int verifyMidiHeader(const unsigned char *array, int size) {
        return
-         (size>6) &&
+               (size>6) &&
                (array[1]==0x02) &&
                (array[2]=='M') &&
                (array[3]=='T') &&
@@ -75,26 +79,26 @@ int verifyMidiHeader(unsigned char* array, int size) {
        ;
 }
 
-int verifyWaveHeader(unsigned char* array, int size) {
+int verifyWaveHeader(const unsigned char *array, int size) {
        return
                (size>1)&&(array[1]==0x01)
        ;
 }
 
-int verifySpeakerHeader(unsigned char* array, int size) {
+int verifySpeakerHeader(const unsigned char *array, int size) {
        return
                (size>2)&&(array[1]==0x00) /* &&!(size%3) */
        ;
 }
 
-int verifyHeader(unsigned char* array, int size) {
-       if (verifyLevelHeader(array,size)) return 1;
-       if (verifyMidiHeader(array,size)) return 4;
-       if (verifyImageHeader(array,size)) return 2;
-       if (verifyPaletteHeader(array,size)) return 6;
-       if (verifyWaveHeader(array,size)) return 3;
-       if (verifySpeakerHeader(array,size)) return 7;
-       return 05;
+int verifyHeader(const unsigned char *array, int size) {
+       if (verifyLevelHeader  (array,size)) return RES_TYPE_LEVEL;
+       if (verifyMidiHeader   (array,size)) return RES_TYPE_MIDI;
+       if (verifyImageHeader  (array,size)) return RES_TYPE_IMAGE;
+       if (verifyPaletteHeader(array,size)) return RES_TYPE_PALETTE;
+       if (verifyWaveHeader   (array,size)) return RES_TYPE_WAVE;
+       if (verifySpeakerHeader(array,size)) return RES_TYPE_PCSPEAKER;
+       return RES_TYPE_BINARY;
 }
 
 const char* getExtDesc(int type) {
@@ -103,105 +107,237 @@ const char* getExtDesc(int type) {
 }
 
 /***************************************************************\
-|                      Parsing resource file                    |
+|                Partial Resource List Functions                |
+\***************************************************************/
+
+static tResIdList partialList;
+
+void parseGivenPath(char* path) {
+       /*
+               PRE:  partialList.list was not allocated
+               POST:
+                partialList.count=0 and partialList.list=NULL if all resources
+                path was trimed in the "@"
+       */
+
+       int i;
+       int separator=0;
+       int resourceValue;
+       int j=0;
+       unsigned char n;
+
+       /* Check if the variable wasn't initialized before */
+       if (partialList.count!=0) return;
+       partialList.list=NULL;
+
+       /* Validates the NULL path */
+       if (path==NULL) return;
+
+       /* Locate the string separation */
+       while (path[separator]&&path[separator]!='@') separator++;
+
+       /* If no separation */
+       if (!path[separator]) return; /* There was no separator */
+
+       /* Count values, separate them with '\0' and alloc memory */
+       partialList.count=1;
+       path[separator]=0; /* Trim the path to the separator */
+       i=++separator;
+       while(path[i]) {
+               if (path[i]==',') {
+                       partialList.count++;
+                       path[i]=0;
+               }
+               i++;
+       }
+       partialList.list=(tResIdListItem*)malloc(sizeof(tResIdListItem)*partialList.count);
+
+       /* Parse values and save them in the list */
+       resourceValue=0;
+       for(i=separator;j!=partialList.count;i++) {
+               n=path[i];
+               if ((0x2F<n)&&(n<0x3A)) {
+                       resourceValue=resourceValue*10+(n-'0');
+               } else {
+                       if (n) {
+                               partialList.list[j].idType=eString;
+                               partialList.list[j].value=(char*)strallocandcopy(repairFolders(path+separator));
+                               while (path[i]) i++;
+                       } else {
+                               partialList.list[j].idType=eValue;
+                               partialList.list[j].value=(void*)resourceValue;
+                       }
+                       resourceValue=0;
+                       separator=i+1;
+                       j++;
+               }
+       }
+}
+
+int isInThePartialList(const char* vFile, int value) {
+       /*
+               Cases:
+                       "path/path@"                    all files are false
+                       "path/path"                     all files are true
+                       "path/path@12file/jjj.bmp,777"  only file "12file/jjj.bmp" and id 777 are true
+                       "path/path@1,2,3"               only ids 1, 2 and 3 are true
+       */
+       int i;
+       char* file;
+
+       if (!partialList.count) return 1;
+       file=(char*)repairFolders(vFile);
+
+       for (i=0;i<partialList.count;i++) {
+               if (partialList.list[i].idType==eValue) {
+                       if (value==(int)partialList.list[i].value) return 1;
+               } else {
+                       if (file)
+                               if (equalsIgnoreCase(file,(char*)partialList.list[i].value)) return 1;
+               }
+       }
+       return 0;
+}
+
+void freePartialList() {
+       int i;
+       for (i=0;i<partialList.count;i++) {
+               if (partialList.list[i].idType==eString)
+                       free(partialList.list[i].value);
+       }
+       partialList.count=0;
+}
+
+/***************************************************************\
+|                       Checksum handling                       |
+\***************************************************************/
+
+int checkSum(unsigned char* data,int size) {
+       unsigned char  checksum = 1;
+
+       /* calculates the checksum */
+       while (size--) checksum+=*(data++);
+       return !checksum;
+}
+
+/***************************************************************\
+|                     Parsing resource file                     |
 \***************************************************************/
 
-//Initializes the resource table
+/* Initializes the resource table */
 void emptyTable(tResource* r[]) {
        int i=MAX_RES_COUNT;
        while (i--) *(r++)=NULL;
 }
 
-//TODO: use a static XML tree and two functions: parseFile and freeXmlStructure
-
-//Resources input xml tree. Private+abstract variable
+/* Resources input xml tree. Private+abstract variable */
 static tTag* xmlStructure=NULL; /* Keeping the parsed file structure in memory will save a lot of time */
 
-
-//parse file
-char parseFile(const char* vFile, const char* datFile, tResource* r[]) {
-       //Declare error variable
+int parseStructure(const char* vFile) {
+       static const char defaultXmlFile[]=RES_XML_RESOURC_XML;
        int error=0;
 
-       //Generate xml structure if doesn't exist
-       if (xmlStructure==NULL) xmlStructure=parseXmlFile(vFile,&error);
-       if (error) {
-               xmlStructure=NULL;
-               return error;
+       /* Generate xml structure if doesn't exist */
+       if (xmlStructure==NULL) {
+               /* Set default values */
+               if (vFile==NULL) vFile=defaultXmlFile;
+               xmlStructure=parseXmlFile(vFile,&error);
        }
+       if (error) xmlStructure=NULL;
+       return error;
+}
+
+/* parse file */
+int parseFile(const char* vFile, const char* datFile, tResource* r[]) {
+       /* Declare error variable */
+       int error;
+       tPassWork pass;
 
-       //Use the xml structure to Generate the resource structure of the file
+       /* Generate xml structure if doesn't exist */
+       if ((error=(parseStructure(vFile)))) return error;
+
+       /* Use the xml structure to Generate the resource structure of the file */
        emptyTable(r);
-       workTree(xmlStructure,datFile,r);
+       pass.datFile=datFile;
+       pass.r=r;
+       workTree(xmlStructure,&pass,workTag);
 
-       //All done
+       /* All done */
        return 0;
 }
 
 void freeParsedStructure() {
-       //Free if exist
+       /* Free if exist */
        if (xmlStructure!=NULL) freeTagStructure(xmlStructure);
-
-       //Reinitializes the veriable
+       /* Reinitializes the variable */
        xmlStructure=NULL;
-
-       return;
 }
 
+/***************************************************************\
+|                     Unknown.xml primitives                    |
+\***************************************************************/
 
-//Resources output to xml functions. Private+abstract variable
+/* Resources output to xml functions. Private+abstract variable */
 static FILE* unknownXmlFile=NULL;
 
-void AddToUnknownXml(const char* vFiledat,unsigned short id,const char* ext,char type,const char* vDirExt,unsigned short pal) {
-       //Open file if not open
+void AddToUnknownXml(const char* vFiledatWithPath,unsigned short id,const char* ext,char type,const char* vDirExt,unsigned short pal,const char* vFiledat,int optionflag,int count) {
+       /* Open file if not open */
        if (unknownXmlFile==NULL) {
                char xmlFile[MAX_FILENAME_SIZE];
-               sprintf(xmlFile,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_XML,vDirExt,vFiledat);
+               sprintf(xmlFile,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_XML,vDirExt,vFiledatWithPath);
 
-               //Open file
-               if (!writeOpen(xmlFile,&unknownXmlFile)) return;
+               /* Open file */
+               if (!writeOpen(xmlFile,&unknownXmlFile,optionflag)) return;
 
-               //Save headers
+               /* Save headers */
                if (type==6) pal=id;
                fprintf(unknownXmlFile,RES_XML_UNKNOWN_START,
-                       vFiledat,vFiledat,pal
+                       vFiledat,vFiledatWithPath,pal
                );
        }
 
-       //Write item
+       /* Write item */
        fprintf(unknownXmlFile,RES_XML_UNKNOWN_ITEM,
-               id,id,ext,getExtDesc(type),id
-       ); //To the xml output
+               id,getExtDesc(type),count,ext,getExtDesc(type),getExtDesc(type),count
+       ); /* To the xml output */
 }
 
-void endUnknownXml() {
+static unsigned int typeCount[RES_TYPECOUNT]; /* initialized in 0 */
+
+void endUnknownXml(int optionflag, const char* backupExtension) {
        if (unknownXmlFile!=NULL) {
+               int i;
                fprintf(unknownXmlFile,RES_XML_UNKNOWN_END);
-               fclose(unknownXmlFile);
+               writeCloseOk(unknownXmlFile,optionflag,backupExtension);
                unknownXmlFile=NULL;
+               for (i=0;i<RES_TYPECOUNT;i++) typeCount[i]=0;
        }
 }
 
-//Resources extra functions
-void getFileName(char* vFileext,const char* vDirExt,tResource* r,short id,const char* vFiledat, const char* vDatFileName) {
-       static const char extarray[8][4]=RES_FILE_EXTENSIONS;
-       const char* ext;
+/***************************************************************\
+|                   Resources extra functions                   |
+\***************************************************************/
+
+void getFileName(char* vFileext,const char* vDirExt,tResource* r,unsigned short id,const char* vFiledat, const char* vDatFileName,int optionflag, const char* backupExtension) {
+       static const char* extarray[]=RES_FILE_EXTENSIONS;
+       int pos;
 
        if (r->path==NULL) {
-               ext=extarray[((r->type<=7)&&(r->type>=0))?r->type:5];
-               //set filename
-               sprintf(vFileext,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_FILES,vDirExt,vDatFileName,id,ext);
-               AddToUnknownXml(vDatFileName,id,ext,r->type,vDirExt,r->palette);
+               pos=((r->type<RES_TYPECOUNT)&&(r->type>=0))?r->type:RES_TYPE_BINARY;
+               typeCount[pos]++;
+
+               /* set filename */
+               sprintf(vFileext,RES_XML_UNKNOWN_PATH""RES_XML_UNKNOWN_FILES,vDirExt,vDatFileName,getExtDesc(pos),typeCount[pos],extarray[pos]);
+               AddToUnknownXml(vDatFileName,id,extarray[pos],r->type,vDirExt,r->palette,vFiledat,optionflag,typeCount[pos]);
        } else {
-               //set filename
+               /* set filename */
                sprintf(vFileext,"%s/%s",vDirExt,r->path);
        }
 }
 
-//Search files for the Import feature
-int importDir(const char* directory, const char* vResFile, int* pOption, const char* backupExtension,const char* vDatDirectory, FILE* output) {
-       //TODO send to a function called by parseFile & importDir
-       //Declare error variable
+/* Search files for the Import feature */
+int importDir(const char* directory, const char* vResFile, int pOption, const char* backupExtension,const char* vDatDirectory, FILE* output) {
+       /* Declare error variable */
        int error=0;
        char* datfile;
        char* recursive;
@@ -209,34 +345,95 @@ int importDir(const char* directory, const char* vResFile, int* pOption, const c
        int sizeOfFile;
        int result;
 
-       //Generate xml structure if doesn't exist
-       if (xmlStructure==NULL) xmlStructure=parseXmlFile(vResFile,&error);
-       if (error) {
-               xmlStructure=NULL;
-               return error;
-       }
+       /* Generate xml structure if doesn't exist */
+       if ((error=(parseStructure(vResFile)))) return error;
 
-       //Use the xml structure to Generate the file list
-       getFiles(xmlStructure);
+       /* Use the xml structure to Generate the file list */
+       workTree(xmlStructure,NULL,addFileToList);
 
        while(datfile=getFileFromList()) {
                sizeOfPath=strlen(vDatDirectory);
                sizeOfFile=strlen(datfile);
 
-               //Generate full vDatDirectory/datfile path
-               recursive=getMemory(sizeOfPath+1+sizeOfFile);
+               /* Generate full vDatDirectory/datfile path */
+               recursive=(char*)malloc(sizeOfPath+sizeOfFile+2);
                memcpy(recursive,vDatDirectory,sizeOfPath);
                recursive[sizeOfPath]=DIR_SEPARATOR;
                memcpy(recursive+sizeOfPath+1,datfile,sizeOfFile+1);
 
-               //Run program
+               /* Run program */
                result=prMain(pOption, backupExtension,directory,vResFile,recursive,datfile,NULL,output);
-               //Free mem
+               /* Free memory */
                free(datfile);
                free(recursive);
        }
 
-       //All done
+       /* All done */
        return result;
 }
 
+int isntADatFile(const char* testFile, const char* vResFile) {
+       /*
+               Results:
+                       0  Is a dat file
+                       1  It isn't a dat file
+                       -1 Parse error
+                       -2 No memory
+                       -3 Attribute not recognized
+                       -4 File not found
+       */
+
+       /* Declare result variable */
+       int result;
+       char* gottenFile;
+
+       /* Generate xml structure if doesn't exist */
+       if ((result=(parseStructure(vResFile)))) return result;
+
+       /* Use the xml structure to Generate the file list */
+       workTree(xmlStructure,NULL,addFileToList);
+       while((gottenFile=(getFileFromList()))) {
+               result=result||equalsIgnoreCase(gottenFile,testFile);
+               free(gottenFile);
+       }
+
+       /* All done */
+       return !result;
+}
+
+/***************************************************************\
+|                Resource tree browsing for DLL                 |
+\***************************************************************/
+
+#ifdef DLL
+
+tTag* resourceTreeGetRoot () {
+       return xmlStructure;
+}
+
+tTag* resourceTreeGetNext (tTag* whereAmI) {
+       return whereAmI->next;
+}
+
+tTag* resourceTreeGetChild(tTag* whereAmI) {
+       return whereAmI->child;
+}
+
+int   resourceTreeGetInfo (tTag* whereAmI,     char** tag, char** desc, char** path, char** file, char** itemtype, char** name, char** palette, char** type, char** value, char** version, char** number) {
+       if (whereAmI==NULL) return 0;
+       *tag=whereAmI->tag;
+       *desc=whereAmI->desc;
+       *path=whereAmI->path;
+       *file=whereAmI->file;
+       *itemtype=whereAmI->itemtype;
+       *name=whereAmI->name;
+       *palette=whereAmI->palette;
+       *type=whereAmI->type;
+       *value=whereAmI->value;
+       *version=whereAmI->version;
+       *number=whereAmI->number;
+       return 1;
+}
+
+#endif
+
index 67a8bb1d37a157126756cb44593eac9d17c13f8e..ce89ee0fbb2a7b8d750f4fa80571e917e00a9cd7 100644 (file)
@@ -1,11 +1,45 @@
-#include "memory.h"
+/*  Princed V3 - Prince of Persia Level Editor for PC Version
+    Copyright (C) 2003 Princed Development Team
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    The authors of this program may be contacted at http://forum.princed.com.ar
+*/
 
+/*
+memory.c: Princed Resources : Memory handling
+¯¯¯¯¯¯¯¯
+ Copyright 2003 Princed Development Team
+  Created: 20 Dec 2003
+
+  Author: Enrique Calot <ecalot.cod@princed.com.ar>
+  Version: 1.01 (2004-Feb-13)
+
+ Note:
+  DO NOT remove this copyright notice
+*/
+
+#include "memory.h"
+#include <string.h>
+\r
 char* strallocandcopy(const char* text) {
        int size;
        char* aux;
        if (text==NULL) return NULL;
        size=strlen(text)+1;
-       aux=getMemory(size);
+       aux=(char*)malloc(size);
        if (aux) memcpy(aux,text,size);
        return aux;
 }
index 10e34a16128c09ca11b945e5a2ba5aa3629d4296..8497f6fc64a6baeaa14a859627f916685ae4a55e 100644 (file)
 */
 
 /*
-compress.c: Princed Resources : Image Compressor
+compress.c: Princed Resources : Image Compression Library
 ¯¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 2.00 (2004-Mar-07)
 
  Note:
   DO NOT remove this copyright notice
@@ -39,71 +40,125 @@ compress.c: Princed Resources : Image Compressor
 #include <string.h>
 #include "compress.h"
 #include "memory.h"
-
-//reserved memory for the Lzx algorithm
-#define MAX_MOD_SIZE_IN_LZX 32001                     /* 38401 */
-//modulus to be used in the 10 bits of the algorithm
-#define MAX_MXD_SIZE_IN_LZX 0x400
+#include "pr.h"
 
 /***************************************************************\
-|                Compression algorithm handling                 |
+|                        Image transpose                        |
 \***************************************************************/
 
-//Determines where the transposed byte must be saved
-int transpose(int x,int n,int m) {
-       return ((x%m)*((n+1)/2))+(int)(x/m);
+/* Determines where the transposed byte must be saved */
+int transpose(int x,int w,int h) {
+       return ((x%h)*(w))+(int)(x/h);
+}
+
+void transposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[transpose(cursor,image->widthInBytes,image->height)]=image->pix[cursor];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
 }
 
-//B3 and B4 expansion algorithm sub function
+void antiTransposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[cursor]=image->pix[transpose(cursor,image->widthInBytes,image->height)];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
+}
+
+/***************************************************************\
+|                    Uncompression algorithms                   |
+\***************************************************************/
+
+/* LZG expansion algorithm sub function */
 unsigned char popBit(unsigned char *byte) {
-  unsigned char bit=(unsigned char)((*byte)&1);
-  (*byte)>>=1;
-  return bit;
+       unsigned char bit=(unsigned char)((*byte)&1);
+       (*byte)>>=1;
+       return bit;
 }
 
-//Expands B3/B4 algorithm
-void expandLzx(unsigned /* note: if error remove signed */char* array,tImage* img, int *i,int cursor, int virtualSize) {
+/* Expands LZ Groody algorithm. This is the core of PR */
+int expandLzg(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
        char k;
-       int pos,h;
+       int location,h,cursor=0,pos=0;
        unsigned char maskbyte,rep;
 
-       for(pos=0;pos<MAX_MXD_SIZE_IN_LZX;(*img).pix[pos]=0,pos++); //clean output garbage
-       while (cursor<virtualSize) {
-               maskbyte=array[*i];(*i)++;
-               for (k=8;k&&(cursor<virtualSize);k--) {
+       if ((image->pix=getMemory(/*imageSize*/MAX_MOD_SIZE_IN_LZG))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+       for(location=0;location<MAX_MOD_SIZE_IN_LZG;image->pix[location]=0,location++); /* clean output garbage */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               maskbyte=array[pos++];
+               for (k=8;k&&(cursor<imageSize);k--) {
                        if (popBit(&maskbyte)) {
-                               (*img).pix[cursor]=array[*i];(*i)++;cursor++;
+                               image->pix[cursor++]=array[pos++];
                        } else {
-                               pos=66+((0x100)*((rep=array[*i])&3))+(unsigned char)array[(*i)+1];(*i)+=2;
+                               location=66+(((rep=array[pos])&3)<<8)+(unsigned char)array[pos+1];pos+=2;
                                rep=(unsigned char)((rep>>2)+3);
-                               while (rep--) { //Be careful in big images
-                                       h=cursor/MAX_MXD_SIZE_IN_LZX-(pos%MAX_MXD_SIZE_IN_LZX>cursor%MAX_MXD_SIZE_IN_LZX);
-                                       (*img).pix[cursor]=(*img).pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZX+pos%MAX_MXD_SIZE_IN_LZX];cursor++;pos++;
+                               while (rep--) { /* Be careful in big images */
+                                       h=cursor/MAX_MXD_SIZE_IN_LZG-((location%MAX_MXD_SIZE_IN_LZG)>(cursor%MAX_MXD_SIZE_IN_LZG));
+                                       image->pix[cursor++]=image->pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZG+(location++)%MAX_MXD_SIZE_IN_LZG];
+
+//                                     h=((cursor-(location&0x3FF))&(~0x3FF));
+//                                     image->pix[cursor]=image->pix[((h<0)?0:h)+(location&0x3FF)];
+       //                              cursor++;location++;
                                }
                        }
                }
        }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
+}
+
+/* Expands RLE algorithm */
+int expandRle(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
+       int cursor=0;
+       register signed char rep;
+       int pos=0;
+
+       if ((image->pix=getMemory(imageSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               rep=(signed char)(array[pos++]);
+               if (rep<0) {
+                       /* Negative */
+                       while (rep++) image->pix[cursor++]=array[pos];
+                       pos++;
+               } else {
+                       /* Positive */
+                       rep=~rep;
+                       while (rep++) image->pix[cursor++]=array[pos++];
+               }
+       }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
 }
 
-//Compress B1/B2 algorithm
+/***************************************************************\
+|                    Compression algorithms                     |
+\***************************************************************/
+
+/* Compress using the Run Length Encoding algorithm */
 void compressRle(unsigned char* data,tImage* img,int *dataSize) {
-       //Declare pointers
+       /* Declare pointers */
        unsigned char* cursorData  = data;
        char*          counter;
-       unsigned char* cursorPix   = (*img).pix;
-       unsigned char* imgEnd      = (*img).pix+(*dataSize);
+       unsigned char* cursorPix   = img->pix;
+       unsigned char* imgEnd      = img->pix+(*dataSize);
 
        while (cursorPix<imgEnd) {
-               //Step 1: Create counter
+               /* Step 1: Create counter */
                *(counter=(char*)(cursorData++))=-1;
 
-               //Step 2: Look and copy the string until a repeated byte is found
+               /* Step 2: Look and copy the string until a repeated byte is found */
                while (
                        (cursorPix<imgEnd)&&
                        (
                                (*cursorPix!=*(cursorPix+1))||
                                (
-                                       (*cursorPix==*(cursorPix+1))&&
+                                       /*(*cursorPix==*(cursorPix+1))&&*/
                                        ((cursorPix+1)<imgEnd)&&
                                        (*cursorPix!=*(cursorPix+2))
                                )
@@ -116,169 +171,154 @@ void compressRle(unsigned char* data,tImage* img,int *dataSize) {
                        cursorData++;
                }
 
-               //Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions
+               /* Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions */
                if (*counter==-1) {
-                       while ((cursorPix<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
+                       while ((cursorPix+1<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
                                cursorPix++;
                                (*counter)--;
                        }
 
-                       *(cursorData)=*(cursorPix); //Print repeated char
+                       *(cursorData)=*(cursorPix); /* Print repeated char */
                        cursorPix++;
                        cursorData++;
                }
        }
+
        *(cursorData++)=0;
        *(cursorData++)=*(cursorPix);
-       *dataSize=(int)((long int)cursorData-(long int)data); //Note: casted to long for portability with 64 bits architectures
+       *dataSize=(int)((long int)cursorData-(long int)data)-2; /* Note: casted to long for portability with 64 bits architectures */
 }
 
-//Expands an array into an image
-int mExpandGraphic(unsigned char* array,tImage *image, int virtualSize) {
-       /*
-               Reads array and extracts tImage
-               returns the next image address or -1 in case of error
+/***************************************************************\
+|               Main compress and expand graphics               |
+\***************************************************************/
 
+/*
                Header info:
-                char checksum, short int height, short int width, (char)0, char compressionType
-                normaly: (* ignored types)
-                checksum* - height - 00 - width - 00 - 00* - compression type
+                1 byte  - checksum           char checksum
+                2 bytes - height             short int height
+                2 bytes - width              short int width
+                1 byte  - 00                 (char)0
+                1 byte  - compression type   unsigned char compressionType
+*/
+
+/* Expands an array into an image */
+int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes) {
+       /*
+               Reads data and extracts tImage
+               returns the next image address or -1 in case of error
        */
 
-  int cursor=0;
-  int i=1;
-
-  //Get memory for the image
-       image->height=((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]) ;
-       i=i+2;
-       image->width =((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]);
-       i=i+2;
-       (*image).size  =(*image).height*(*image).width;
-       virtualSize=(((*image).height*((*image).width+((*image).width&1)))>>1);
-       i++;
-
-  switch ((unsigned char)array[i++]) {
-               case PG_COMP_RAW: //No Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               (*image).pix[cursor++]=array[i++];
-                       }
+       int imageSizeInBytes;
+       int result;
+
+       data++;
+       image->height=((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+       image->width =((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+
+       if (*(data++)) return -1; /* Verify format */
+       image->type=(unsigned char)(*(data++));
+       dataSizeInBytes-=7;
+
+       if (image->type&0xB0) {
+               image->widthInBytes=(image->width+1)/2;
+       } else {
+               image->widthInBytes=(image->width+7)/8;
+       }
+       imageSizeInBytes=image->widthInBytes*image->height;
+
+       switch (getAlgor(image->type)) {
+               case COMPRESS_RAW: /* No Compression Algorithm */
+                       if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+                       memcpy(image->pix,data,imageSizeInBytes);
+                       result=COMPRESS_RESULT_SUCCESS;
                        break;
-               case PG_COMP_RLE_LR: //RLE Left to Right Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(cursor++)]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[(cursor++)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_RLE_UD: //RLE Up to Down Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(transpose(cursor++,(*image).width,(*image).height))]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[transpose(cursor++,(*image).width,(*image).height)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_LR: //LZ Groody Up to Down Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       expandLzx(array,image,&i,cursor,virtualSize);
+               case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_UD: //LZ Groody Left to Right Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       {
-                       unsigned char* outputaux=getMemory(virtualSize);
-                       expandLzx(array,image,&i,cursor,virtualSize);
-                       //Transpose
-                 while (cursor<virtualSize) outputaux[transpose(cursor,(*image).width,(*image).height)]=(*image).pix[cursor++];
-                       free((*image).pix);
-                       (*image).pix=outputaux;
-                       }
+               case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
                default:
-                return -1;
+                       result=COMPRESS_RESULT_FATAL;
+                       break;
        }
-       return i;
+       return result; /* Ok */
 }
 
-#define COMPRESS_WORKING_ALGORITHMS 3
-
-//Compress an image into an array
-int mCompressGraphic(unsigned char* data,tImage* i, int* size) {
-       //Declare variables
+/* Compress an image into binary data */
+int mCompressGraphic(unsigned char* data,tImage* image, int* dataSizeInBytes) {
+       /* Declare variables */
+       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
        int            compressedSize [COMPRESS_WORKING_ALGORITHMS];
        int            algorithm;
-       int            cursor;
-       int            virtualsize;
-       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
-       unsigned char* outputaux;
-
-       //Initialize variables
-       virtualsize=(((i->width)+1)>>1)*i->height;
-       outputaux=getMemory(virtualsize);
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) compressedSize[cursor]=virtualsize;
-       cursor=0;
-
-       //B0
-       compressed[0]=getMemory(compressedSize[0]);
-       memcpy(compressed[0],i->pix,compressedSize[0]);
-
-       //B1
-       compressed[1]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       compressRle(compressed[1],i,&(compressedSize[1]));
-
-       //B2
-       compressed[2]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       //Transpose
-  while (cursor<=virtualsize) {
-               outputaux[cursor]=i->pix[transpose(cursor,i->width,i->height)];
-               cursor++;
-       }
-       free(i->pix);
-       i->pix=outputaux;
-       compressRle(compressed[2],i,&(compressedSize[2]));
-
-       /*Process results*/
-
-       //Select the best compression (find minimum)
-       *size=compressedSize[0];
-       algorithm=0;
-       for (cursor=1;cursor<3;cursor++) {
-               if ((*size)>compressedSize[cursor]) {
-                       (*size)=compressedSize[cursor];
-                       algorithm=cursor;
+       int            i;
+       int            imageSizeInBytes;
+
+       /* Initialize variables */
+       imageSizeInBytes=image->widthInBytes*image->height;
+       for (i=0;i<COMPRESS_WORKING_ALGORITHMS;i++) compressedSize[i]=imageSizeInBytes;
+
+       /*
+               Perform all compressions
+       */
+
+       /* COMPRESS_RAW */
+       compressed[COMPRESS_RAW]=getMemory(compressedSize[COMPRESS_RAW]);
+       memcpy(compressed[COMPRESS_RAW],image->pix,compressedSize[COMPRESS_RAW]);
+
+       /* COMPRESS_RLE_LR */
+       compressed[COMPRESS_RLE_LR]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       compressRle(compressed[COMPRESS_RLE_LR],image,&(compressedSize[COMPRESS_RLE_LR]));
+
+       /* COMPRESS_RLE_UD */
+       compressed[COMPRESS_RLE_UD]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       antiTransposeImage(image,imageSizeInBytes);
+       compressRle(compressed[COMPRESS_RLE_UD],image,&(compressedSize[COMPRESS_RLE_UD]));
+
+       /*
+               Process results
+       */
+
+       /* Select the best compression (find minimum) */
+       *dataSizeInBytes=compressedSize[COMPRESS_RAW];
+       algorithm=COMPRESS_RAW;
+       for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+               if ((*dataSizeInBytes)>compressedSize[i]) {
+                       (*dataSizeInBytes)=compressedSize[i];
+                       algorithm=i;
                }
        }
 
-       //Copy the best algorithm in the compressed data
-       memcpy(data+6,compressed[algorithm],*size);
-       (*size)+=6;
-
-       //Write header
-       //(16 bits)height (Intel short int format)
-       data[0]=i->height;
-       data[1]=i->height>>8;
-       //(16 bits)width (Intel short int format)
-       data[2]=i->width;
-       data[3]=i->width>>8;
-       //(12 bits)000000001011+(4 bits)algorithm
-       data[4]=0;
-       data[5]=0xB0+algorithm;
+       /* Copy the best algorithm in the compressed data */
+       memcpy(data+6,compressed[algorithm],*dataSizeInBytes);
+       (*dataSizeInBytes)+=6;
 
-       //Free all compression attempts
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) free(compressed[cursor]);
+       /*
+               Write header
+       */
+
+       /* (16 bits)height (Intel short int format) */
+       data[0]=image->height;
+       data[1]=image->height>>8;
+       /* (16 bits)width (Intel short int format) */
+       data[2]=image->width;
+       data[3]=image->width>>8;
+       /* (8 bits)00000000+(4 bits)palette type+(4 bits)algorithm */
+       data[4]=0;
+       data[5]=image->type|algorithm;
 
+       /* Free all compression attempts */
+       for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
        return 1;
 }
index 10e34a16128c09ca11b945e5a2ba5aa3629d4296..8497f6fc64a6baeaa14a859627f916685ae4a55e 100644 (file)
 */
 
 /*
-compress.c: Princed Resources : Image Compressor
+compress.c: Princed Resources : Image Compression Library
 ¯¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 2.00 (2004-Mar-07)
 
  Note:
   DO NOT remove this copyright notice
@@ -39,71 +40,125 @@ compress.c: Princed Resources : Image Compressor
 #include <string.h>
 #include "compress.h"
 #include "memory.h"
-
-//reserved memory for the Lzx algorithm
-#define MAX_MOD_SIZE_IN_LZX 32001                     /* 38401 */
-//modulus to be used in the 10 bits of the algorithm
-#define MAX_MXD_SIZE_IN_LZX 0x400
+#include "pr.h"
 
 /***************************************************************\
-|                Compression algorithm handling                 |
+|                        Image transpose                        |
 \***************************************************************/
 
-//Determines where the transposed byte must be saved
-int transpose(int x,int n,int m) {
-       return ((x%m)*((n+1)/2))+(int)(x/m);
+/* Determines where the transposed byte must be saved */
+int transpose(int x,int w,int h) {
+       return ((x%h)*(w))+(int)(x/h);
+}
+
+void transposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[transpose(cursor,image->widthInBytes,image->height)]=image->pix[cursor];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
 }
 
-//B3 and B4 expansion algorithm sub function
+void antiTransposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[cursor]=image->pix[transpose(cursor,image->widthInBytes,image->height)];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
+}
+
+/***************************************************************\
+|                    Uncompression algorithms                   |
+\***************************************************************/
+
+/* LZG expansion algorithm sub function */
 unsigned char popBit(unsigned char *byte) {
-  unsigned char bit=(unsigned char)((*byte)&1);
-  (*byte)>>=1;
-  return bit;
+       unsigned char bit=(unsigned char)((*byte)&1);
+       (*byte)>>=1;
+       return bit;
 }
 
-//Expands B3/B4 algorithm
-void expandLzx(unsigned /* note: if error remove signed */char* array,tImage* img, int *i,int cursor, int virtualSize) {
+/* Expands LZ Groody algorithm. This is the core of PR */
+int expandLzg(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
        char k;
-       int pos,h;
+       int location,h,cursor=0,pos=0;
        unsigned char maskbyte,rep;
 
-       for(pos=0;pos<MAX_MXD_SIZE_IN_LZX;(*img).pix[pos]=0,pos++); //clean output garbage
-       while (cursor<virtualSize) {
-               maskbyte=array[*i];(*i)++;
-               for (k=8;k&&(cursor<virtualSize);k--) {
+       if ((image->pix=getMemory(/*imageSize*/MAX_MOD_SIZE_IN_LZG))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+       for(location=0;location<MAX_MOD_SIZE_IN_LZG;image->pix[location]=0,location++); /* clean output garbage */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               maskbyte=array[pos++];
+               for (k=8;k&&(cursor<imageSize);k--) {
                        if (popBit(&maskbyte)) {
-                               (*img).pix[cursor]=array[*i];(*i)++;cursor++;
+                               image->pix[cursor++]=array[pos++];
                        } else {
-                               pos=66+((0x100)*((rep=array[*i])&3))+(unsigned char)array[(*i)+1];(*i)+=2;
+                               location=66+(((rep=array[pos])&3)<<8)+(unsigned char)array[pos+1];pos+=2;
                                rep=(unsigned char)((rep>>2)+3);
-                               while (rep--) { //Be careful in big images
-                                       h=cursor/MAX_MXD_SIZE_IN_LZX-(pos%MAX_MXD_SIZE_IN_LZX>cursor%MAX_MXD_SIZE_IN_LZX);
-                                       (*img).pix[cursor]=(*img).pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZX+pos%MAX_MXD_SIZE_IN_LZX];cursor++;pos++;
+                               while (rep--) { /* Be careful in big images */
+                                       h=cursor/MAX_MXD_SIZE_IN_LZG-((location%MAX_MXD_SIZE_IN_LZG)>(cursor%MAX_MXD_SIZE_IN_LZG));
+                                       image->pix[cursor++]=image->pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZG+(location++)%MAX_MXD_SIZE_IN_LZG];
+
+//                                     h=((cursor-(location&0x3FF))&(~0x3FF));
+//                                     image->pix[cursor]=image->pix[((h<0)?0:h)+(location&0x3FF)];
+       //                              cursor++;location++;
                                }
                        }
                }
        }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
+}
+
+/* Expands RLE algorithm */
+int expandRle(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
+       int cursor=0;
+       register signed char rep;
+       int pos=0;
+
+       if ((image->pix=getMemory(imageSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               rep=(signed char)(array[pos++]);
+               if (rep<0) {
+                       /* Negative */
+                       while (rep++) image->pix[cursor++]=array[pos];
+                       pos++;
+               } else {
+                       /* Positive */
+                       rep=~rep;
+                       while (rep++) image->pix[cursor++]=array[pos++];
+               }
+       }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
 }
 
-//Compress B1/B2 algorithm
+/***************************************************************\
+|                    Compression algorithms                     |
+\***************************************************************/
+
+/* Compress using the Run Length Encoding algorithm */
 void compressRle(unsigned char* data,tImage* img,int *dataSize) {
-       //Declare pointers
+       /* Declare pointers */
        unsigned char* cursorData  = data;
        char*          counter;
-       unsigned char* cursorPix   = (*img).pix;
-       unsigned char* imgEnd      = (*img).pix+(*dataSize);
+       unsigned char* cursorPix   = img->pix;
+       unsigned char* imgEnd      = img->pix+(*dataSize);
 
        while (cursorPix<imgEnd) {
-               //Step 1: Create counter
+               /* Step 1: Create counter */
                *(counter=(char*)(cursorData++))=-1;
 
-               //Step 2: Look and copy the string until a repeated byte is found
+               /* Step 2: Look and copy the string until a repeated byte is found */
                while (
                        (cursorPix<imgEnd)&&
                        (
                                (*cursorPix!=*(cursorPix+1))||
                                (
-                                       (*cursorPix==*(cursorPix+1))&&
+                                       /*(*cursorPix==*(cursorPix+1))&&*/
                                        ((cursorPix+1)<imgEnd)&&
                                        (*cursorPix!=*(cursorPix+2))
                                )
@@ -116,169 +171,154 @@ void compressRle(unsigned char* data,tImage* img,int *dataSize) {
                        cursorData++;
                }
 
-               //Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions
+               /* Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions */
                if (*counter==-1) {
-                       while ((cursorPix<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
+                       while ((cursorPix+1<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
                                cursorPix++;
                                (*counter)--;
                        }
 
-                       *(cursorData)=*(cursorPix); //Print repeated char
+                       *(cursorData)=*(cursorPix); /* Print repeated char */
                        cursorPix++;
                        cursorData++;
                }
        }
+
        *(cursorData++)=0;
        *(cursorData++)=*(cursorPix);
-       *dataSize=(int)((long int)cursorData-(long int)data); //Note: casted to long for portability with 64 bits architectures
+       *dataSize=(int)((long int)cursorData-(long int)data)-2; /* Note: casted to long for portability with 64 bits architectures */
 }
 
-//Expands an array into an image
-int mExpandGraphic(unsigned char* array,tImage *image, int virtualSize) {
-       /*
-               Reads array and extracts tImage
-               returns the next image address or -1 in case of error
+/***************************************************************\
+|               Main compress and expand graphics               |
+\***************************************************************/
 
+/*
                Header info:
-                char checksum, short int height, short int width, (char)0, char compressionType
-                normaly: (* ignored types)
-                checksum* - height - 00 - width - 00 - 00* - compression type
+                1 byte  - checksum           char checksum
+                2 bytes - height             short int height
+                2 bytes - width              short int width
+                1 byte  - 00                 (char)0
+                1 byte  - compression type   unsigned char compressionType
+*/
+
+/* Expands an array into an image */
+int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes) {
+       /*
+               Reads data and extracts tImage
+               returns the next image address or -1 in case of error
        */
 
-  int cursor=0;
-  int i=1;
-
-  //Get memory for the image
-       image->height=((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]) ;
-       i=i+2;
-       image->width =((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]);
-       i=i+2;
-       (*image).size  =(*image).height*(*image).width;
-       virtualSize=(((*image).height*((*image).width+((*image).width&1)))>>1);
-       i++;
-
-  switch ((unsigned char)array[i++]) {
-               case PG_COMP_RAW: //No Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               (*image).pix[cursor++]=array[i++];
-                       }
+       int imageSizeInBytes;
+       int result;
+
+       data++;
+       image->height=((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+       image->width =((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+
+       if (*(data++)) return -1; /* Verify format */
+       image->type=(unsigned char)(*(data++));
+       dataSizeInBytes-=7;
+
+       if (image->type&0xB0) {
+               image->widthInBytes=(image->width+1)/2;
+       } else {
+               image->widthInBytes=(image->width+7)/8;
+       }
+       imageSizeInBytes=image->widthInBytes*image->height;
+
+       switch (getAlgor(image->type)) {
+               case COMPRESS_RAW: /* No Compression Algorithm */
+                       if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+                       memcpy(image->pix,data,imageSizeInBytes);
+                       result=COMPRESS_RESULT_SUCCESS;
                        break;
-               case PG_COMP_RLE_LR: //RLE Left to Right Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(cursor++)]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[(cursor++)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_RLE_UD: //RLE Up to Down Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(transpose(cursor++,(*image).width,(*image).height))]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[transpose(cursor++,(*image).width,(*image).height)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_LR: //LZ Groody Up to Down Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       expandLzx(array,image,&i,cursor,virtualSize);
+               case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_UD: //LZ Groody Left to Right Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       {
-                       unsigned char* outputaux=getMemory(virtualSize);
-                       expandLzx(array,image,&i,cursor,virtualSize);
-                       //Transpose
-                 while (cursor<virtualSize) outputaux[transpose(cursor,(*image).width,(*image).height)]=(*image).pix[cursor++];
-                       free((*image).pix);
-                       (*image).pix=outputaux;
-                       }
+               case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
                default:
-                return -1;
+                       result=COMPRESS_RESULT_FATAL;
+                       break;
        }
-       return i;
+       return result; /* Ok */
 }
 
-#define COMPRESS_WORKING_ALGORITHMS 3
-
-//Compress an image into an array
-int mCompressGraphic(unsigned char* data,tImage* i, int* size) {
-       //Declare variables
+/* Compress an image into binary data */
+int mCompressGraphic(unsigned char* data,tImage* image, int* dataSizeInBytes) {
+       /* Declare variables */
+       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
        int            compressedSize [COMPRESS_WORKING_ALGORITHMS];
        int            algorithm;
-       int            cursor;
-       int            virtualsize;
-       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
-       unsigned char* outputaux;
-
-       //Initialize variables
-       virtualsize=(((i->width)+1)>>1)*i->height;
-       outputaux=getMemory(virtualsize);
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) compressedSize[cursor]=virtualsize;
-       cursor=0;
-
-       //B0
-       compressed[0]=getMemory(compressedSize[0]);
-       memcpy(compressed[0],i->pix,compressedSize[0]);
-
-       //B1
-       compressed[1]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       compressRle(compressed[1],i,&(compressedSize[1]));
-
-       //B2
-       compressed[2]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       //Transpose
-  while (cursor<=virtualsize) {
-               outputaux[cursor]=i->pix[transpose(cursor,i->width,i->height)];
-               cursor++;
-       }
-       free(i->pix);
-       i->pix=outputaux;
-       compressRle(compressed[2],i,&(compressedSize[2]));
-
-       /*Process results*/
-
-       //Select the best compression (find minimum)
-       *size=compressedSize[0];
-       algorithm=0;
-       for (cursor=1;cursor<3;cursor++) {
-               if ((*size)>compressedSize[cursor]) {
-                       (*size)=compressedSize[cursor];
-                       algorithm=cursor;
+       int            i;
+       int            imageSizeInBytes;
+
+       /* Initialize variables */
+       imageSizeInBytes=image->widthInBytes*image->height;
+       for (i=0;i<COMPRESS_WORKING_ALGORITHMS;i++) compressedSize[i]=imageSizeInBytes;
+
+       /*
+               Perform all compressions
+       */
+
+       /* COMPRESS_RAW */
+       compressed[COMPRESS_RAW]=getMemory(compressedSize[COMPRESS_RAW]);
+       memcpy(compressed[COMPRESS_RAW],image->pix,compressedSize[COMPRESS_RAW]);
+
+       /* COMPRESS_RLE_LR */
+       compressed[COMPRESS_RLE_LR]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       compressRle(compressed[COMPRESS_RLE_LR],image,&(compressedSize[COMPRESS_RLE_LR]));
+
+       /* COMPRESS_RLE_UD */
+       compressed[COMPRESS_RLE_UD]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       antiTransposeImage(image,imageSizeInBytes);
+       compressRle(compressed[COMPRESS_RLE_UD],image,&(compressedSize[COMPRESS_RLE_UD]));
+
+       /*
+               Process results
+       */
+
+       /* Select the best compression (find minimum) */
+       *dataSizeInBytes=compressedSize[COMPRESS_RAW];
+       algorithm=COMPRESS_RAW;
+       for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+               if ((*dataSizeInBytes)>compressedSize[i]) {
+                       (*dataSizeInBytes)=compressedSize[i];
+                       algorithm=i;
                }
        }
 
-       //Copy the best algorithm in the compressed data
-       memcpy(data+6,compressed[algorithm],*size);
-       (*size)+=6;
-
-       //Write header
-       //(16 bits)height (Intel short int format)
-       data[0]=i->height;
-       data[1]=i->height>>8;
-       //(16 bits)width (Intel short int format)
-       data[2]=i->width;
-       data[3]=i->width>>8;
-       //(12 bits)000000001011+(4 bits)algorithm
-       data[4]=0;
-       data[5]=0xB0+algorithm;
+       /* Copy the best algorithm in the compressed data */
+       memcpy(data+6,compressed[algorithm],*dataSizeInBytes);
+       (*dataSizeInBytes)+=6;
 
-       //Free all compression attempts
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) free(compressed[cursor]);
+       /*
+               Write header
+       */
+
+       /* (16 bits)height (Intel short int format) */
+       data[0]=image->height;
+       data[1]=image->height>>8;
+       /* (16 bits)width (Intel short int format) */
+       data[2]=image->width;
+       data[3]=image->width>>8;
+       /* (8 bits)00000000+(4 bits)palette type+(4 bits)algorithm */
+       data[4]=0;
+       data[5]=image->type|algorithm;
 
+       /* Free all compression attempts */
+       for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
        return 1;
 }
index 10e34a16128c09ca11b945e5a2ba5aa3629d4296..8497f6fc64a6baeaa14a859627f916685ae4a55e 100644 (file)
 */
 
 /*
-compress.c: Princed Resources : Image Compressor
+compress.c: Princed Resources : Image Compression Library
 ¯¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 2.00 (2004-Mar-07)
 
  Note:
   DO NOT remove this copyright notice
@@ -39,71 +40,125 @@ compress.c: Princed Resources : Image Compressor
 #include <string.h>
 #include "compress.h"
 #include "memory.h"
-
-//reserved memory for the Lzx algorithm
-#define MAX_MOD_SIZE_IN_LZX 32001                     /* 38401 */
-//modulus to be used in the 10 bits of the algorithm
-#define MAX_MXD_SIZE_IN_LZX 0x400
+#include "pr.h"
 
 /***************************************************************\
-|                Compression algorithm handling                 |
+|                        Image transpose                        |
 \***************************************************************/
 
-//Determines where the transposed byte must be saved
-int transpose(int x,int n,int m) {
-       return ((x%m)*((n+1)/2))+(int)(x/m);
+/* Determines where the transposed byte must be saved */
+int transpose(int x,int w,int h) {
+       return ((x%h)*(w))+(int)(x/h);
+}
+
+void transposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[transpose(cursor,image->widthInBytes,image->height)]=image->pix[cursor];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
 }
 
-//B3 and B4 expansion algorithm sub function
+void antiTransposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[cursor]=image->pix[transpose(cursor,image->widthInBytes,image->height)];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
+}
+
+/***************************************************************\
+|                    Uncompression algorithms                   |
+\***************************************************************/
+
+/* LZG expansion algorithm sub function */
 unsigned char popBit(unsigned char *byte) {
-  unsigned char bit=(unsigned char)((*byte)&1);
-  (*byte)>>=1;
-  return bit;
+       unsigned char bit=(unsigned char)((*byte)&1);
+       (*byte)>>=1;
+       return bit;
 }
 
-//Expands B3/B4 algorithm
-void expandLzx(unsigned /* note: if error remove signed */char* array,tImage* img, int *i,int cursor, int virtualSize) {
+/* Expands LZ Groody algorithm. This is the core of PR */
+int expandLzg(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
        char k;
-       int pos,h;
+       int location,h,cursor=0,pos=0;
        unsigned char maskbyte,rep;
 
-       for(pos=0;pos<MAX_MXD_SIZE_IN_LZX;(*img).pix[pos]=0,pos++); //clean output garbage
-       while (cursor<virtualSize) {
-               maskbyte=array[*i];(*i)++;
-               for (k=8;k&&(cursor<virtualSize);k--) {
+       if ((image->pix=getMemory(/*imageSize*/MAX_MOD_SIZE_IN_LZG))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+       for(location=0;location<MAX_MOD_SIZE_IN_LZG;image->pix[location]=0,location++); /* clean output garbage */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               maskbyte=array[pos++];
+               for (k=8;k&&(cursor<imageSize);k--) {
                        if (popBit(&maskbyte)) {
-                               (*img).pix[cursor]=array[*i];(*i)++;cursor++;
+                               image->pix[cursor++]=array[pos++];
                        } else {
-                               pos=66+((0x100)*((rep=array[*i])&3))+(unsigned char)array[(*i)+1];(*i)+=2;
+                               location=66+(((rep=array[pos])&3)<<8)+(unsigned char)array[pos+1];pos+=2;
                                rep=(unsigned char)((rep>>2)+3);
-                               while (rep--) { //Be careful in big images
-                                       h=cursor/MAX_MXD_SIZE_IN_LZX-(pos%MAX_MXD_SIZE_IN_LZX>cursor%MAX_MXD_SIZE_IN_LZX);
-                                       (*img).pix[cursor]=(*img).pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZX+pos%MAX_MXD_SIZE_IN_LZX];cursor++;pos++;
+                               while (rep--) { /* Be careful in big images */
+                                       h=cursor/MAX_MXD_SIZE_IN_LZG-((location%MAX_MXD_SIZE_IN_LZG)>(cursor%MAX_MXD_SIZE_IN_LZG));
+                                       image->pix[cursor++]=image->pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZG+(location++)%MAX_MXD_SIZE_IN_LZG];
+
+//                                     h=((cursor-(location&0x3FF))&(~0x3FF));
+//                                     image->pix[cursor]=image->pix[((h<0)?0:h)+(location&0x3FF)];
+       //                              cursor++;location++;
                                }
                        }
                }
        }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
+}
+
+/* Expands RLE algorithm */
+int expandRle(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
+       int cursor=0;
+       register signed char rep;
+       int pos=0;
+
+       if ((image->pix=getMemory(imageSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               rep=(signed char)(array[pos++]);
+               if (rep<0) {
+                       /* Negative */
+                       while (rep++) image->pix[cursor++]=array[pos];
+                       pos++;
+               } else {
+                       /* Positive */
+                       rep=~rep;
+                       while (rep++) image->pix[cursor++]=array[pos++];
+               }
+       }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
 }
 
-//Compress B1/B2 algorithm
+/***************************************************************\
+|                    Compression algorithms                     |
+\***************************************************************/
+
+/* Compress using the Run Length Encoding algorithm */
 void compressRle(unsigned char* data,tImage* img,int *dataSize) {
-       //Declare pointers
+       /* Declare pointers */
        unsigned char* cursorData  = data;
        char*          counter;
-       unsigned char* cursorPix   = (*img).pix;
-       unsigned char* imgEnd      = (*img).pix+(*dataSize);
+       unsigned char* cursorPix   = img->pix;
+       unsigned char* imgEnd      = img->pix+(*dataSize);
 
        while (cursorPix<imgEnd) {
-               //Step 1: Create counter
+               /* Step 1: Create counter */
                *(counter=(char*)(cursorData++))=-1;
 
-               //Step 2: Look and copy the string until a repeated byte is found
+               /* Step 2: Look and copy the string until a repeated byte is found */
                while (
                        (cursorPix<imgEnd)&&
                        (
                                (*cursorPix!=*(cursorPix+1))||
                                (
-                                       (*cursorPix==*(cursorPix+1))&&
+                                       /*(*cursorPix==*(cursorPix+1))&&*/
                                        ((cursorPix+1)<imgEnd)&&
                                        (*cursorPix!=*(cursorPix+2))
                                )
@@ -116,169 +171,154 @@ void compressRle(unsigned char* data,tImage* img,int *dataSize) {
                        cursorData++;
                }
 
-               //Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions
+               /* Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions */
                if (*counter==-1) {
-                       while ((cursorPix<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
+                       while ((cursorPix+1<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
                                cursorPix++;
                                (*counter)--;
                        }
 
-                       *(cursorData)=*(cursorPix); //Print repeated char
+                       *(cursorData)=*(cursorPix); /* Print repeated char */
                        cursorPix++;
                        cursorData++;
                }
        }
+
        *(cursorData++)=0;
        *(cursorData++)=*(cursorPix);
-       *dataSize=(int)((long int)cursorData-(long int)data); //Note: casted to long for portability with 64 bits architectures
+       *dataSize=(int)((long int)cursorData-(long int)data)-2; /* Note: casted to long for portability with 64 bits architectures */
 }
 
-//Expands an array into an image
-int mExpandGraphic(unsigned char* array,tImage *image, int virtualSize) {
-       /*
-               Reads array and extracts tImage
-               returns the next image address or -1 in case of error
+/***************************************************************\
+|               Main compress and expand graphics               |
+\***************************************************************/
 
+/*
                Header info:
-                char checksum, short int height, short int width, (char)0, char compressionType
-                normaly: (* ignored types)
-                checksum* - height - 00 - width - 00 - 00* - compression type
+                1 byte  - checksum           char checksum
+                2 bytes - height             short int height
+                2 bytes - width              short int width
+                1 byte  - 00                 (char)0
+                1 byte  - compression type   unsigned char compressionType
+*/
+
+/* Expands an array into an image */
+int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes) {
+       /*
+               Reads data and extracts tImage
+               returns the next image address or -1 in case of error
        */
 
-  int cursor=0;
-  int i=1;
-
-  //Get memory for the image
-       image->height=((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]) ;
-       i=i+2;
-       image->width =((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]);
-       i=i+2;
-       (*image).size  =(*image).height*(*image).width;
-       virtualSize=(((*image).height*((*image).width+((*image).width&1)))>>1);
-       i++;
-
-  switch ((unsigned char)array[i++]) {
-               case PG_COMP_RAW: //No Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               (*image).pix[cursor++]=array[i++];
-                       }
+       int imageSizeInBytes;
+       int result;
+
+       data++;
+       image->height=((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+       image->width =((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+
+       if (*(data++)) return -1; /* Verify format */
+       image->type=(unsigned char)(*(data++));
+       dataSizeInBytes-=7;
+
+       if (image->type&0xB0) {
+               image->widthInBytes=(image->width+1)/2;
+       } else {
+               image->widthInBytes=(image->width+7)/8;
+       }
+       imageSizeInBytes=image->widthInBytes*image->height;
+
+       switch (getAlgor(image->type)) {
+               case COMPRESS_RAW: /* No Compression Algorithm */
+                       if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+                       memcpy(image->pix,data,imageSizeInBytes);
+                       result=COMPRESS_RESULT_SUCCESS;
                        break;
-               case PG_COMP_RLE_LR: //RLE Left to Right Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(cursor++)]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[(cursor++)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_RLE_UD: //RLE Up to Down Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(transpose(cursor++,(*image).width,(*image).height))]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[transpose(cursor++,(*image).width,(*image).height)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_LR: //LZ Groody Up to Down Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       expandLzx(array,image,&i,cursor,virtualSize);
+               case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_UD: //LZ Groody Left to Right Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       {
-                       unsigned char* outputaux=getMemory(virtualSize);
-                       expandLzx(array,image,&i,cursor,virtualSize);
-                       //Transpose
-                 while (cursor<virtualSize) outputaux[transpose(cursor,(*image).width,(*image).height)]=(*image).pix[cursor++];
-                       free((*image).pix);
-                       (*image).pix=outputaux;
-                       }
+               case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
                default:
-                return -1;
+                       result=COMPRESS_RESULT_FATAL;
+                       break;
        }
-       return i;
+       return result; /* Ok */
 }
 
-#define COMPRESS_WORKING_ALGORITHMS 3
-
-//Compress an image into an array
-int mCompressGraphic(unsigned char* data,tImage* i, int* size) {
-       //Declare variables
+/* Compress an image into binary data */
+int mCompressGraphic(unsigned char* data,tImage* image, int* dataSizeInBytes) {
+       /* Declare variables */
+       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
        int            compressedSize [COMPRESS_WORKING_ALGORITHMS];
        int            algorithm;
-       int            cursor;
-       int            virtualsize;
-       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
-       unsigned char* outputaux;
-
-       //Initialize variables
-       virtualsize=(((i->width)+1)>>1)*i->height;
-       outputaux=getMemory(virtualsize);
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) compressedSize[cursor]=virtualsize;
-       cursor=0;
-
-       //B0
-       compressed[0]=getMemory(compressedSize[0]);
-       memcpy(compressed[0],i->pix,compressedSize[0]);
-
-       //B1
-       compressed[1]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       compressRle(compressed[1],i,&(compressedSize[1]));
-
-       //B2
-       compressed[2]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       //Transpose
-  while (cursor<=virtualsize) {
-               outputaux[cursor]=i->pix[transpose(cursor,i->width,i->height)];
-               cursor++;
-       }
-       free(i->pix);
-       i->pix=outputaux;
-       compressRle(compressed[2],i,&(compressedSize[2]));
-
-       /*Process results*/
-
-       //Select the best compression (find minimum)
-       *size=compressedSize[0];
-       algorithm=0;
-       for (cursor=1;cursor<3;cursor++) {
-               if ((*size)>compressedSize[cursor]) {
-                       (*size)=compressedSize[cursor];
-                       algorithm=cursor;
+       int            i;
+       int            imageSizeInBytes;
+
+       /* Initialize variables */
+       imageSizeInBytes=image->widthInBytes*image->height;
+       for (i=0;i<COMPRESS_WORKING_ALGORITHMS;i++) compressedSize[i]=imageSizeInBytes;
+
+       /*
+               Perform all compressions
+       */
+
+       /* COMPRESS_RAW */
+       compressed[COMPRESS_RAW]=getMemory(compressedSize[COMPRESS_RAW]);
+       memcpy(compressed[COMPRESS_RAW],image->pix,compressedSize[COMPRESS_RAW]);
+
+       /* COMPRESS_RLE_LR */
+       compressed[COMPRESS_RLE_LR]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       compressRle(compressed[COMPRESS_RLE_LR],image,&(compressedSize[COMPRESS_RLE_LR]));
+
+       /* COMPRESS_RLE_UD */
+       compressed[COMPRESS_RLE_UD]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       antiTransposeImage(image,imageSizeInBytes);
+       compressRle(compressed[COMPRESS_RLE_UD],image,&(compressedSize[COMPRESS_RLE_UD]));
+
+       /*
+               Process results
+       */
+
+       /* Select the best compression (find minimum) */
+       *dataSizeInBytes=compressedSize[COMPRESS_RAW];
+       algorithm=COMPRESS_RAW;
+       for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+               if ((*dataSizeInBytes)>compressedSize[i]) {
+                       (*dataSizeInBytes)=compressedSize[i];
+                       algorithm=i;
                }
        }
 
-       //Copy the best algorithm in the compressed data
-       memcpy(data+6,compressed[algorithm],*size);
-       (*size)+=6;
-
-       //Write header
-       //(16 bits)height (Intel short int format)
-       data[0]=i->height;
-       data[1]=i->height>>8;
-       //(16 bits)width (Intel short int format)
-       data[2]=i->width;
-       data[3]=i->width>>8;
-       //(12 bits)000000001011+(4 bits)algorithm
-       data[4]=0;
-       data[5]=0xB0+algorithm;
+       /* Copy the best algorithm in the compressed data */
+       memcpy(data+6,compressed[algorithm],*dataSizeInBytes);
+       (*dataSizeInBytes)+=6;
 
-       //Free all compression attempts
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) free(compressed[cursor]);
+       /*
+               Write header
+       */
+
+       /* (16 bits)height (Intel short int format) */
+       data[0]=image->height;
+       data[1]=image->height>>8;
+       /* (16 bits)width (Intel short int format) */
+       data[2]=image->width;
+       data[3]=image->width>>8;
+       /* (8 bits)00000000+(4 bits)palette type+(4 bits)algorithm */
+       data[4]=0;
+       data[5]=image->type|algorithm;
 
+       /* Free all compression attempts */
+       for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
        return 1;
 }
index 10e34a16128c09ca11b945e5a2ba5aa3629d4296..8497f6fc64a6baeaa14a859627f916685ae4a55e 100644 (file)
 */
 
 /*
-compress.c: Princed Resources : Image Compressor
+compress.c: Princed Resources : Image Compression Library
 ¯¯¯¯¯¯¯¯¯¯
- Copyright 2003 Princed Development Team
+ Copyright 2003, 2004 Princed Development Team
   Created: 24 Aug 2003
 
   Author: Enrique Calot <ecalot.cod@princed.com.ar>
   Version: 1.01 (2003-Oct-23)
+  Version: 2.00 (2004-Mar-07)
 
  Note:
   DO NOT remove this copyright notice
@@ -39,71 +40,125 @@ compress.c: Princed Resources : Image Compressor
 #include <string.h>
 #include "compress.h"
 #include "memory.h"
-
-//reserved memory for the Lzx algorithm
-#define MAX_MOD_SIZE_IN_LZX 32001                     /* 38401 */
-//modulus to be used in the 10 bits of the algorithm
-#define MAX_MXD_SIZE_IN_LZX 0x400
+#include "pr.h"
 
 /***************************************************************\
-|                Compression algorithm handling                 |
+|                        Image transpose                        |
 \***************************************************************/
 
-//Determines where the transposed byte must be saved
-int transpose(int x,int n,int m) {
-       return ((x%m)*((n+1)/2))+(int)(x/m);
+/* Determines where the transposed byte must be saved */
+int transpose(int x,int w,int h) {
+       return ((x%h)*(w))+(int)(x/h);
+}
+
+void transposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[transpose(cursor,image->widthInBytes,image->height)]=image->pix[cursor];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
 }
 
-//B3 and B4 expansion algorithm sub function
+void antiTransposeImage(tImage* image,int size) {
+       unsigned char* outputaux=getMemory(size);
+       int cursor=0;
+
+       while (cursor<size) {outputaux[cursor]=image->pix[transpose(cursor,image->widthInBytes,image->height)];cursor++;}
+       free(image->pix);
+       image->pix=outputaux;
+}
+
+/***************************************************************\
+|                    Uncompression algorithms                   |
+\***************************************************************/
+
+/* LZG expansion algorithm sub function */
 unsigned char popBit(unsigned char *byte) {
-  unsigned char bit=(unsigned char)((*byte)&1);
-  (*byte)>>=1;
-  return bit;
+       unsigned char bit=(unsigned char)((*byte)&1);
+       (*byte)>>=1;
+       return bit;
 }
 
-//Expands B3/B4 algorithm
-void expandLzx(unsigned /* note: if error remove signed */char* array,tImage* img, int *i,int cursor, int virtualSize) {
+/* Expands LZ Groody algorithm. This is the core of PR */
+int expandLzg(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
        char k;
-       int pos,h;
+       int location,h,cursor=0,pos=0;
        unsigned char maskbyte,rep;
 
-       for(pos=0;pos<MAX_MXD_SIZE_IN_LZX;(*img).pix[pos]=0,pos++); //clean output garbage
-       while (cursor<virtualSize) {
-               maskbyte=array[*i];(*i)++;
-               for (k=8;k&&(cursor<virtualSize);k--) {
+       if ((image->pix=getMemory(/*imageSize*/MAX_MOD_SIZE_IN_LZG))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+       for(location=0;location<MAX_MOD_SIZE_IN_LZG;image->pix[location]=0,location++); /* clean output garbage */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               maskbyte=array[pos++];
+               for (k=8;k&&(cursor<imageSize);k--) {
                        if (popBit(&maskbyte)) {
-                               (*img).pix[cursor]=array[*i];(*i)++;cursor++;
+                               image->pix[cursor++]=array[pos++];
                        } else {
-                               pos=66+((0x100)*((rep=array[*i])&3))+(unsigned char)array[(*i)+1];(*i)+=2;
+                               location=66+(((rep=array[pos])&3)<<8)+(unsigned char)array[pos+1];pos+=2;
                                rep=(unsigned char)((rep>>2)+3);
-                               while (rep--) { //Be careful in big images
-                                       h=cursor/MAX_MXD_SIZE_IN_LZX-(pos%MAX_MXD_SIZE_IN_LZX>cursor%MAX_MXD_SIZE_IN_LZX);
-                                       (*img).pix[cursor]=(*img).pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZX+pos%MAX_MXD_SIZE_IN_LZX];cursor++;pos++;
+                               while (rep--) { /* Be careful in big images */
+                                       h=cursor/MAX_MXD_SIZE_IN_LZG-((location%MAX_MXD_SIZE_IN_LZG)>(cursor%MAX_MXD_SIZE_IN_LZG));
+                                       image->pix[cursor++]=image->pix[((h<0)?0:h)*MAX_MXD_SIZE_IN_LZG+(location++)%MAX_MXD_SIZE_IN_LZG];
+
+//                                     h=((cursor-(location&0x3FF))&(~0x3FF));
+//                                     image->pix[cursor]=image->pix[((h<0)?0:h)+(location&0x3FF)];
+       //                              cursor++;location++;
                                }
                        }
                }
        }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
+}
+
+/* Expands RLE algorithm */
+int expandRle(const unsigned char* array, int arraySize, tImage* image, int imageSize) {
+       int cursor=0;
+       register signed char rep;
+       int pos=0;
+
+       if ((image->pix=getMemory(imageSize+128))==NULL) return COMPRESS_RESULT_FATAL; /* reserve memory */
+
+       /* main loop */
+       while (cursor<imageSize) {
+               rep=(signed char)(array[pos++]);
+               if (rep<0) {
+                       /* Negative */
+                       while (rep++) image->pix[cursor++]=array[pos];
+                       pos++;
+               } else {
+                       /* Positive */
+                       rep=~rep;
+                       while (rep++) image->pix[cursor++]=array[pos++];
+               }
+       }
+       return ((pos==arraySize)&(cursor==imageSize))-1; /* WARNING or SUCCESS */
 }
 
-//Compress B1/B2 algorithm
+/***************************************************************\
+|                    Compression algorithms                     |
+\***************************************************************/
+
+/* Compress using the Run Length Encoding algorithm */
 void compressRle(unsigned char* data,tImage* img,int *dataSize) {
-       //Declare pointers
+       /* Declare pointers */
        unsigned char* cursorData  = data;
        char*          counter;
-       unsigned char* cursorPix   = (*img).pix;
-       unsigned char* imgEnd      = (*img).pix+(*dataSize);
+       unsigned char* cursorPix   = img->pix;
+       unsigned char* imgEnd      = img->pix+(*dataSize);
 
        while (cursorPix<imgEnd) {
-               //Step 1: Create counter
+               /* Step 1: Create counter */
                *(counter=(char*)(cursorData++))=-1;
 
-               //Step 2: Look and copy the string until a repeated byte is found
+               /* Step 2: Look and copy the string until a repeated byte is found */
                while (
                        (cursorPix<imgEnd)&&
                        (
                                (*cursorPix!=*(cursorPix+1))||
                                (
-                                       (*cursorPix==*(cursorPix+1))&&
+                                       /*(*cursorPix==*(cursorPix+1))&&*/
                                        ((cursorPix+1)<imgEnd)&&
                                        (*cursorPix!=*(cursorPix+2))
                                )
@@ -116,169 +171,154 @@ void compressRle(unsigned char* data,tImage* img,int *dataSize) {
                        cursorData++;
                }
 
-               //Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions
+               /* Step 3: If there was a repeated string, let's ignore it and add the cursor with the repetitions */
                if (*counter==-1) {
-                       while ((cursorPix<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
+                       while ((cursorPix+1<imgEnd)&&(*cursorPix==(*(cursorPix+1)))&&((*counter)!=-128)) {
                                cursorPix++;
                                (*counter)--;
                        }
 
-                       *(cursorData)=*(cursorPix); //Print repeated char
+                       *(cursorData)=*(cursorPix); /* Print repeated char */
                        cursorPix++;
                        cursorData++;
                }
        }
+
        *(cursorData++)=0;
        *(cursorData++)=*(cursorPix);
-       *dataSize=(int)((long int)cursorData-(long int)data); //Note: casted to long for portability with 64 bits architectures
+       *dataSize=(int)((long int)cursorData-(long int)data)-2; /* Note: casted to long for portability with 64 bits architectures */
 }
 
-//Expands an array into an image
-int mExpandGraphic(unsigned char* array,tImage *image, int virtualSize) {
-       /*
-               Reads array and extracts tImage
-               returns the next image address or -1 in case of error
+/***************************************************************\
+|               Main compress and expand graphics               |
+\***************************************************************/
 
+/*
                Header info:
-                char checksum, short int height, short int width, (char)0, char compressionType
-                normaly: (* ignored types)
-                checksum* - height - 00 - width - 00 - 00* - compression type
+                1 byte  - checksum           char checksum
+                2 bytes - height             short int height
+                2 bytes - width              short int width
+                1 byte  - 00                 (char)0
+                1 byte  - compression type   unsigned char compressionType
+*/
+
+/* Expands an array into an image */
+int mExpandGraphic(const unsigned char* data,tImage *image, int dataSizeInBytes) {
+       /*
+               Reads data and extracts tImage
+               returns the next image address or -1 in case of error
        */
 
-  int cursor=0;
-  int i=1;
-
-  //Get memory for the image
-       image->height=((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]) ;
-       i=i+2;
-       image->width =((unsigned char)array[(i)])+256*((unsigned char)array[(i+1)]);
-       i=i+2;
-       (*image).size  =(*image).height*(*image).width;
-       virtualSize=(((*image).height*((*image).width+((*image).width&1)))>>1);
-       i++;
-
-  switch ((unsigned char)array[i++]) {
-               case PG_COMP_RAW: //No Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               (*image).pix[cursor++]=array[i++];
-                       }
+       int imageSizeInBytes;
+       int result;
+
+       data++;
+       image->height=((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+       image->width =((unsigned char)data[0])+((unsigned char)data[1]<<8);data+=2;
+
+       if (*(data++)) return -1; /* Verify format */
+       image->type=(unsigned char)(*(data++));
+       dataSizeInBytes-=7;
+
+       if (image->type&0xB0) {
+               image->widthInBytes=(image->width+1)/2;
+       } else {
+               image->widthInBytes=(image->width+7)/8;
+       }
+       imageSizeInBytes=image->widthInBytes*image->height;
+
+       switch (getAlgor(image->type)) {
+               case COMPRESS_RAW: /* No Compression Algorithm */
+                       if ((image->pix=getMemory(imageSizeInBytes))==NULL) return COMPRESS_RESULT_FATAL;
+                       memcpy(image->pix,data,imageSizeInBytes);
+                       result=COMPRESS_RESULT_SUCCESS;
                        break;
-               case PG_COMP_RLE_LR: //RLE Left to Right Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(cursor++)]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[(cursor++)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_LR: /* RLE Left to Right Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_RLE_UD: //RLE Up to Down Compression Algorithm
-                 if (((*image).pix=getMemory(virtualSize))==NULL) return -1;
-                 while (cursor<virtualSize) {
-                               if ((signed char)array[i]<0) {
-                                       //negative
-                                       while (array[i]++) (*image).pix[(transpose(cursor++,(*image).width,(*image).height))]=array[i+1];
-                                       i+=2;
-                               } else {
-                                       //Positive
-                                       signed char cx=(signed char)(array[i++]+1);
-                                       while (cx--) (*image).pix[transpose(cursor++,(*image).width,(*image).height)]=array[i++];
-                               }
-                       }
+               case COMPRESS_RLE_UD: /* RLE Up to Down Compression Algorithm */
+                       result=expandRle(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_LR: //LZ Groody Up to Down Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       expandLzx(array,image,&i,cursor,virtualSize);
+               case COMPRESS_LZG_LR: /* LZ Groody Left to Right Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
                        break;
-               case PG_COMP_LZX_UD: //LZ Groody Left to Right Version Compression Algorithm
-                 if (((*image).pix=getMemory(MAX_MOD_SIZE_IN_LZX))==NULL) return -1;
-                       {
-                       unsigned char* outputaux=getMemory(virtualSize);
-                       expandLzx(array,image,&i,cursor,virtualSize);
-                       //Transpose
-                 while (cursor<virtualSize) outputaux[transpose(cursor,(*image).width,(*image).height)]=(*image).pix[cursor++];
-                       free((*image).pix);
-                       (*image).pix=outputaux;
-                       }
+               case COMPRESS_LZG_UD: /* LZ Groody Up to Down Compression Algorithm */
+                       result=expandLzg(data,dataSizeInBytes,image,imageSizeInBytes);
+                       if (result==COMPRESS_RESULT_FATAL) return COMPRESS_RESULT_FATAL;
+                       transposeImage(image,imageSizeInBytes);
                        break;
                default:
-                return -1;
+                       result=COMPRESS_RESULT_FATAL;
+                       break;
        }
-       return i;
+       return result; /* Ok */
 }
 
-#define COMPRESS_WORKING_ALGORITHMS 3
-
-//Compress an image into an array
-int mCompressGraphic(unsigned char* data,tImage* i, int* size) {
-       //Declare variables
+/* Compress an image into binary data */
+int mCompressGraphic(unsigned char* data,tImage* image, int* dataSizeInBytes) {
+       /* Declare variables */
+       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
        int            compressedSize [COMPRESS_WORKING_ALGORITHMS];
        int            algorithm;
-       int            cursor;
-       int            virtualsize;
-       unsigned char* compressed     [COMPRESS_WORKING_ALGORITHMS];
-       unsigned char* outputaux;
-
-       //Initialize variables
-       virtualsize=(((i->width)+1)>>1)*i->height;
-       outputaux=getMemory(virtualsize);
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) compressedSize[cursor]=virtualsize;
-       cursor=0;
-
-       //B0
-       compressed[0]=getMemory(compressedSize[0]);
-       memcpy(compressed[0],i->pix,compressedSize[0]);
-
-       //B1
-       compressed[1]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       compressRle(compressed[1],i,&(compressedSize[1]));
-
-       //B2
-       compressed[2]=getMemory(10*virtualsize+50); //This will reserve 10*(image size)+50 bytes, to allocate the compressed file
-       //Transpose
-  while (cursor<=virtualsize) {
-               outputaux[cursor]=i->pix[transpose(cursor,i->width,i->height)];
-               cursor++;
-       }
-       free(i->pix);
-       i->pix=outputaux;
-       compressRle(compressed[2],i,&(compressedSize[2]));
-
-       /*Process results*/
-
-       //Select the best compression (find minimum)
-       *size=compressedSize[0];
-       algorithm=0;
-       for (cursor=1;cursor<3;cursor++) {
-               if ((*size)>compressedSize[cursor]) {
-                       (*size)=compressedSize[cursor];
-                       algorithm=cursor;
+       int            i;
+       int            imageSizeInBytes;
+
+       /* Initialize variables */
+       imageSizeInBytes=image->widthInBytes*image->height;
+       for (i=0;i<COMPRESS_WORKING_ALGORITHMS;i++) compressedSize[i]=imageSizeInBytes;
+
+       /*
+               Perform all compressions
+       */
+
+       /* COMPRESS_RAW */
+       compressed[COMPRESS_RAW]=getMemory(compressedSize[COMPRESS_RAW]);
+       memcpy(compressed[COMPRESS_RAW],image->pix,compressedSize[COMPRESS_RAW]);
+
+       /* COMPRESS_RLE_LR */
+       compressed[COMPRESS_RLE_LR]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       compressRle(compressed[COMPRESS_RLE_LR],image,&(compressedSize[COMPRESS_RLE_LR]));
+
+       /* COMPRESS_RLE_UD */
+       compressed[COMPRESS_RLE_UD]=getMemory(10*imageSizeInBytes+50); /* This will reserve 10*(image size)+50 bytes, to allocate the compressed file */
+       antiTransposeImage(image,imageSizeInBytes);
+       compressRle(compressed[COMPRESS_RLE_UD],image,&(compressedSize[COMPRESS_RLE_UD]));
+
+       /*
+               Process results
+       */
+
+       /* Select the best compression (find minimum) */
+       *dataSizeInBytes=compressedSize[COMPRESS_RAW];
+       algorithm=COMPRESS_RAW;
+       for (i=COMPRESS_RLE_LR;i<COMPRESS_WORKING_ALGORITHMS;i++) {
+               if ((*dataSizeInBytes)>compressedSize[i]) {
+                       (*dataSizeInBytes)=compressedSize[i];
+                       algorithm=i;
                }
        }
 
-       //Copy the best algorithm in the compressed data
-       memcpy(data+6,compressed[algorithm],*size);
-       (*size)+=6;
-
-       //Write header
-       //(16 bits)height (Intel short int format)
-       data[0]=i->height;
-       data[1]=i->height>>8;
-       //(16 bits)width (Intel short int format)
-       data[2]=i->width;
-       data[3]=i->width>>8;
-       //(12 bits)000000001011+(4 bits)algorithm
-       data[4]=0;
-       data[5]=0xB0+algorithm;
+       /* Copy the best algorithm in the compressed data */
+       memcpy(data+6,compressed[algorithm],*dataSizeInBytes);
+       (*dataSizeInBytes)+=6;
 
-       //Free all compression attempts
-       for (cursor=0;cursor<COMPRESS_WORKING_ALGORITHMS;cursor++) free(compressed[cursor]);
+       /*
+               Write header
+       */
+
+       /* (16 bits)height (Intel short int format) */
+       data[0]=image->height;
+       data[1]=image->height>>8;
+       /* (16 bits)width (Intel short int format) */
+       data[2]=image->width;
+       data[3]=image->width>>8;
+       /* (8 bits)00000000+(4 bits)palette type+(4 bits)algorithm */
+       data[4]=0;
+       data[5]=image->type|algorithm;
 
+       /* Free all compression attempts */
+       for (i=COMPRESS_RAW;i<COMPRESS_WORKING_ALGORITHMS;i++) free(compressed[i]);
        return 1;
 }
index 2e44111f58c6cea5cf795c2c378939da70bfc744..905be4b787128ea462e7d5a600cdcbfb88f4194f 100644 (file)
@@ -27,6 +27,7 @@ pr.c: Main source file for Princed Resources
        Authors
         Coding & main routines
          Enrique Calot
+         Santiago Zamora
 
         Graphic compression algorithms
          Tammo Jan Dijkema
@@ -46,7 +47,7 @@ pr.c: Main source file for Princed Resources
   DO NOT remove this copyright notice
 */
 
-//Headers
+/* Headers */
 #include <stdio.h>
 #include <string.h>
 
@@ -64,6 +65,9 @@ pr.c: Main source file for Princed Resources
 #ifndef DLL
  #ifdef UNIX
   #include <unistd.h>
+  #ifndef LINUX
+   #include "getopt.h"
+  #endif
  #else
   #include "getopt.h"
  #endif
@@ -73,24 +77,34 @@ pr.c: Main source file for Princed Resources
 |                      Main working functions                   |
 \***************************************************************/
 
+FILE* outputStream=NULL;
+
+#ifdef DLL
+void prSetOutput(FILE* output) {
+       outputStream=output;
+}
+#endif
+
+#ifdef DLL
 int prExportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
-       return prExportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL,"");
+       outputStream=stdout;
+       return prExportDatOpt(vDatFile,vDirName,vResFile,export_flag,NULL,NULL,NULL);
 }
+#endif
 
 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
+                                               if file use it, if directory, 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
+                                               NULL is the default file resources.xml
                        char opt              - program options, see below
-                       char * vDatFileName   - name of the file to be extracted
-                                               NULL means predict it from vDatFile (DISABLED!!!)
+                       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
@@ -104,9 +118,9 @@ int prExportDatOpt(const char* vDatFile, const char* vDirName, const char* vResF
                        verbose_flag   - explain what is being done
                        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,
+                       force_flag     - default option, you cannot disable it,
                                         so please make a backup of your files
-x                      backup_flag    - backup your files
+                       backup_flag    - backup your files
 
 
                Return values:
@@ -120,37 +134,59 @@ x                 backup_flag    - backup your files
                        -7 XML File not found
        */
 
-       //Declare variables
+       /* Declare variables */
        tResource* r[MAX_RES_COUNT];
        int a;
-       const char defaultXmlFile[]=RES_XML_RESOURC_XML;
-       //Set default values
-       if (vResFile==NULL) vResFile=defaultXmlFile; //TODO: Send to prMain or main
-
-       //Parse XML and extract the file //TODO: XML parser outside the function
-       a=parseFile(vResFile,vDatFileName,r);
-       if (a<0) return a-3; //parsing errors
-       a=extract(vDatFile,vDirName,r,opt,vDatFileName,datAuthor);
-       return a; //extracting errors/no errors
+       const char* aux;
+       char* currentDatFileName;
+       char* currentDatFile;
+
+       currentDatFile=strallocandcopy(vDatFileName);
+
+       parseGivenPath(currentDatFile);
+
+       if (vDatFileName==NULL) { /* if no special dat file was specified, a path parsed will be used */
+               aux=getFileNameFromPath(vDatFile);
+       } else {
+               aux=currentDatFile;
+       }
+       currentDatFileName=strallocandcopy(aux);
+
+       /* Parse XML and export the file */
+       a=parseFile(vResFile,currentDatFileName,r);
+       if (a<0) {
+               /* parsing errors */
+               a-=3;
+       } else {
+               /* exporting errors/no errors */
+               a=extract(vDatFile,vDirName,r,opt,currentDatFileName,datAuthor,backupExtension);
+       }
+       free(currentDatFileName);
+       free(currentDatFile);
+       freePartialList();
+
+       return a;
 }
 
+#ifdef DLL
 int prImportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
-       return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,"");
+       outputStream=stdout;
+       return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL);
 }
+#endif
 
 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
+                                               if file use it, if directory, 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
+                       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
@@ -161,9 +197,9 @@ int prImportDatOpt(const char* vDatFile, const char* vDirName, const char* vResF
                        verbose_flag   - explain what is being done
                        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
+                       force_flag     - If not set and the file exists it will prompt
+                                        for action
+                       backup_flag    - backup your files
 
 
                Return values:
@@ -172,146 +208,149 @@ x                       backup_flag    - backup your files
                        -3 No memory
                        -4 XML Attribute not recognized
                        -5 XML File not found
-                       00 File succesfully compiled
+                       00 File successfully imported
                        positive number: number of missing files
        */
 
-       //Declare variables
+       /* Declare variables */
        tResource* r[MAX_RES_COUNT];
        int a;
-       const char defaultXmlFile[]=RES_XML_RESOURC_XML;
+       const char* aux;
+       char* currentDatFileName;
 
-       //Set default values
-       if (vResFile==NULL) vResFile=defaultXmlFile;
+       if (vDatFileName==NULL) { /* if no special dat file was specified, a path parsed will be used */
+               aux=getFileNameFromPath(vDatFile);
+       } else {
+               aux=vDatFileName;
+       }
+       currentDatFileName=strallocandcopy(aux);
 
-       //Parse XML and compile files
-       a=parseFile     (vResFile,vDatFileName,r);
-       if (a<0) return a-1;
-       a=compile (vDatFile, vDirName,r,opt,vDatFileName);
+       /* Parse XML and import files */
+       a=parseFile(vResFile,currentDatFileName,r);
+       if (a<0) {
+               /* parsing errors */
+               a-=1;
+       } else {
+               /* importing errors/no errors */
+               a=compile (vDatFile, vDirName,r,opt,currentDatFileName,backupExtension);
+       }
+       free(currentDatFileName);
        return a;
 }
 
-
 /***************************************************************\
 |                     M A I N   P R O G R A M                   |
 \***************************************************************/
 
-void syntax(FILE* output) {
-       fprintf(output,PARSING_HELP);
+void syntax() {
+       fprintf(outputStream,PARSING_HELP);
 }
 
-int prMain(int* pOption, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
+int prMain(int optionflag, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
 
-       //declare variables
-       int returnValue=1;
-       char* currentDatFileName;
-       const char* aux;
+       /* declare variables */
+       int returnValue;
 
-       if (datfilename==NULL) {
-               aux=getFileNameFromPath(datfile);
-       } else {
-               aux=datfilename;
-       }
-
-       currentDatFileName=strallocandcopy(aux);
+       outputStream=output;
 
-       //do selected tasks
-       if (optionflag&export_flag) {
+       /* do selected tasks */
+       if (hasFlag(export_flag)) { /* Export file */
                char* array[]=PR_TEXT_EXPORT_ARRAY;
-               fprintf(output,"Extracting '%s' to '%s' with %04x\r\n",datfile,dirName,optionflag);
-               returnValue=prExportDatOpt(datfile,dirName,resFile,optionflag,currentDatFileName,datAuthor,extension);
+               fprintf(output,PR_TEXT_TASK_EXTRACT,datfile,dirName);
+               returnValue=prExportDatOpt(datfile,dirName,resFile,optionflag,datfilename,datAuthor,extension);
                fprintf(output,PR_TEXT_RESULT,array[-returnValue],returnValue);
-       }       else if (optionflag&classify_flag) {
+       }       else if (hasFlag(classify_flag)) { /* Classify file */
                char* array[]=PR_TEXT_CLASSIFY_ARRAY;
-               fprintf(output,"Classifing '%s'\r\n",datfile);
+               fprintf(output,PR_TEXT_TASK_CLASSIFY,datfile);
                returnValue=prVerifyDatType(datfile);
-               fprintf(output,PR_TEXT_RESULT,array[2+returnValue],returnValue);
-       }       else if (optionflag&import_flag) {
+               if (hasFlag(cgi_flag)) {
+                       fprintf(output,PR_CGI_TEXT2,returnValue);
+               } else {
+                       fprintf(output,PR_TEXT_RESULT,array[2+returnValue],returnValue);
+               }
+       }       else if (hasFlag(import_flag)) { /* Import file */
                char* array[]=PR_TEXT_IMPORT_ARRAY;
-               fprintf(output,"Compiling '%s' from '%s' with %04x\r\n",datfile,dirName,optionflag);
-               returnValue=prImportDatOpt(datfile,dirName,resFile,optionflag,currentDatFileName,extension);
+               fprintf(output,PR_TEXT_TASK_COMPILE,datfile,dirName);
+               returnValue=prImportDatOpt(datfile,dirName,resFile,optionflag,datfilename,extension);
                if (returnValue<=0) {
                        fprintf(output,PR_TEXT_RESULT,array[-returnValue],returnValue);
                } else {
                        fprintf(output,PR_TEXT_RESULT_ERR,returnValue);
                }
        } else {
-               syntax(output);
+               syntax();
                returnValue=-1;
        }
-       if (currentDatFileName) free(currentDatFileName);
+
        return returnValue;
 }
 
-//Main program
 #ifndef DLL
 
 /***************************************************************\
 |             Standard executable specific functions            |
 \***************************************************************/
 
-int prStart(int* pOption, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
+int prStart(int optionflag, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor,FILE* output) {
        int result=1;
+       whatIs selectedFile;
+       outputStream=output;
 
-       //Do CGI tasks
-       if (optionflag&cgi_flag) {
-               optionflag&=(~classify_flag);
-               if (!(optionflag&first_flag)) {
-                       fprintf(output,PR_CGI_TEXT1);
-                       optionflag|=first_flag;
-               }
-               if (optionflag==cgi_flag) {
-                       fprintf(output,PR_CGI_TEXT2,prVerifyDatType(datfile));
-                       return 1;
-               } else {
-                       optionflag=help_flag;
-               }
-       }
-
-       //Show about
-       if (!(optionflag&first_flag)) {
+       /* Show about or cgi stuff */
+       if (hasFlag(cgi_flag)) {
+               fprintf(output,PR_CGI_TEXT1);
+       } else {
                fprintf(output,PR_ABOUT);
-               optionflag|=first_flag;
        }
 
-       //If bad syntax or help screen requested
-       if (optionflag&help_flag) {
-               syntax(output);
+       /* Show version screen if requested */
+       if (hasFlag(version_flag)) {
+               fprintf(output,PARSING_ABOUT);
                return -1;
        }
 
-       //If version asked, stop
-       if (optionflag&version_flag) {
+       /* If bad syntax or help screen requested */
+       if (hasFlag(help_flag)) {
+               syntax();
                return -1;
        }
 
-       //Perform tasks depending on the argument
-       if (optionflag&import_flag) {
-               //Check out the xml file to get the files to me compiled
+       /* Perform tasks depending on the argument */
+       if (hasFlag(import_flag)) {
+               /* We have to import something, let's see what the parameters are */
                if (datfile==NULL) {
-                       fprintf(output,"Importing all valid dat files from the currect directory\n");
-                       importDir(dirName,resFile,pOption,extension,".",output);
-               } else if (isDir(datfile)!=eFile) {
-                       fprintf(output,"Importing all valid files from given directory\n");
-                       importDir(dirName,resFile,pOption,extension,datfile,output);
-               } else {
-                       result=prMain(pOption,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
+                       /* no files? let's use the whole current directory */
+                       fprintf(output,PR_TEXT_IMPORTING_CURRENT);
+                       importDir(dirName,resFile,optionflag,extension,".",output);
+               } else if ((selectedFile=isDir(datfile))!=eFile) {
+                       fprintf(output,PR_TEXT_IMPORTING_GIVEN);
+                       if ((selectedFile==eDirectory)||(isntADatFile(getFileNameFromPath(datfile),resFile))) {
+                               /* it's a directory or doesn't exist (but it's not a dat file) */
+                               importDir(dirName,resFile,optionflag,extension,datfile,output);
+                       } else {
+                               /* it doesn't exist but it's a dat file */
+                               result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
+                       }
+               } else { /* it's only one existent file */
+                       result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
                }
        } else {
-
-               //Recursive testing for export/classify
+               /* We have to export/classify something, perhaps we'll need to use somerecursive functions */
                if (datfile==NULL) {
+                       /* If nothing, let's use the current dir and check for all the files there */
                        fprintf(output,PR_TEXT_SCANNING_CURRENT);
-                       recurseDirectory(".",pOption,extension,dirName,resFile,datfilename,datAuthor,output);
-               } else if (isDir(datfile)==eDirectory) {
+                       recurseDirectory(".",optionflag,extension,dirName,resFile,datfilename,datAuthor,output);
+               } else if ((selectedFile=isDir(datfile))==eDirectory) {
+                       /* If it's a directory, let's check for all the files there */
                        fprintf(output,PR_TEXT_SCANNING_GIVEN);
-                       recurseDirectory(datfile,pOption,extension,dirName,resFile,datfilename,datAuthor,output);
-               } else if (isDir(datfile)==eNotFound) {
+                       recurseDirectory(datfile,optionflag,extension,dirName,resFile,datfilename,datAuthor,output);
+               } else if (selectedFile==eNotFound) {
+                       /* If the file doesn't exist, print an error and exit */
                        fprintf(output,PR_TEXT_FILE_NOT_FOUND,datfile);
-                       return 0;
+                       result=0;
                } else {
-
-                       result=prMain(pOption,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
+                       /* If it is a file, just do the tasks for it */
+                       result=prMain(optionflag,extension,dirName,resFile,datfile,datfilename,datAuthor,output);
                }
        }
 
@@ -324,98 +363,111 @@ int prStart(int* pOption, const char* extension,const char* dirName,const char*
 \***************************************************************/
 
 int main (int argc, char **argv) {
-       //declare variables
-       char* datFileName=NULL;
+       /* declare variables */
        char  dirName[MAX_FILENAME_SIZE]=".";
-       char  extension[MAX_EXTENSION_SIZE]=DEFAULT_BACKUP_EXTENSION;
-       char  resFile[MAX_FILENAME_SIZE]=RES_XML_RESOURC_XML;
+       char* datAuthor  =NULL;
+       char* datFileName=NULL;
        char* datFilePath=NULL;
-       char* datAuthor=NULL;
+       char* extension  =NULL;
+       char* resFile    =NULL;
        int   c;
-       int   flag=0;
+       int   optionflag=0;
 
-       //Parse options
-       while (1) {
+       /* Parse command line options */
+       do {
                static struct option long_options[] = PARSING_OPTIONS;
-
-               /* getopt_long stores the option index here. */
                int junk = 0;
-               c = getopt_long (argc, argv, PARSING_CHARS,long_options,&junk);
-
-               /* Detect the end of the options. */
-               if (c == -1) break;
 
+               c = getopt_long(argc,argv,PARSING_CHARS,long_options,&junk);
                switch (c) {
                                case 'c':
-                                       if (flag&(classify_flag|export_flag)) flag|=help_flag;
-                                       flag|=import_flag;
+                               case 'i':
+                                       if (hasFlag(classify_flag|export_flag)) setFlag(help_flag);
+                                       setFlag(import_flag);
                                        if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
                                        break;
+                               case 'g':
+                                       setFlag(cgi_flag); /* if cgi, a classify must be performed */
                                case 'd':
-                                       if (flag&(import_flag|export_flag)) flag|=help_flag;
-                                       flag|=classify_flag;
+                                       if (hasFlag(import_flag|export_flag)) setFlag(help_flag);
+                                       setFlag(classify_flag);
                                        break;
                                case 'x':
                                case 'e':
-                                       if (flag&(classify_flag|import_flag)) flag|=help_flag;
-                                       flag|=export_flag;
+                                       if (hasFlag(classify_flag|import_flag)) setFlag(help_flag);
+                                       setFlag(export_flag);
                                        if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
                                        break;
                                case 'b':
-                                       flag|=backup_flag;
-                                       if (optarg) strncpy(extension,optarg,MAX_FILENAME_SIZE);
+                                       setFlag(backup_flag);
+                                       freeAllocation(extension);
+                                       extension=strallocandcopy(optarg);
                                        break;
                                case 'f':
-                                       flag|=force_flag;
+                                       setFlag(force_flag);
                                        break;
-                               case 'g':
-                                       flag|=cgi_flag;
-                                       break;
-                               case 'm':
-                                       strncpy(resFile,optarg,MAX_FILENAME_SIZE);
+                               case 's':
+                                       freeAllocation(resFile);
+                                       resFile=strallocandcopy(optarg);
                                        break;
                                case 'r':
-                                       flag|=raw_flag;
+#ifndef PR_IGNORE_RAW_OPTION
+                                       setFlag(raw_flag);
                                        break;
+#endif
                                case 'R':
-                                       flag|=recursive_flag;
+                                       setFlag(recursive_flag);
                                        break;
                                case 't':
-                                       if (datFileName!=NULL) free(datFileName);
+                                       freeAllocation(datFileName);
                                        datFileName=strallocandcopy(optarg);
                                        break;
                                case 'a':
-                                       if (datAuthor!=NULL) free(datAuthor);
+                                       freeAllocation(datAuthor);
                                        datAuthor=strallocandcopy(optarg);
                                        break;
                                case 'v':
-                                       flag|=verbose_flag;
-                                       break;
-                               case 1:
-                                       flag|=version_flag;
+                                       setFlag(verbose_flag);
                                        break;
                                case 2:
-                                       flag|=unknown_flag;
+                                       setFlag(unknown_flag);
+                               case -1:
                                        break;
+                               case 1:
+                                       setFlag(version_flag);
                                default:
-                                       flag|=help_flag;
+                                       setFlag(help_flag);
                }
-       }
+       } while (c!=-1);
 
        if (optind < argc) {
-               datFilePath=argv[optind];
+               int size;
+               datFilePath=strallocandcopy(argv[optind]);
+               /* Erase the last "/" if exists. TODO: send to parseGivenPath  */
+               size=strlen(datFilePath);
+               if (size>0) {
+                       size--;
+                       if (isDirSep(datFilePath,size)) datFilePath[size]=0;
+               }
        }
 
-       if (!flag) flag=help_flag;
+       /* At least one of these options must be selected, if not, the user needs help! */
+       if (!(hasFlag(import_flag|export_flag|classify_flag))) setFlag(help_flag);
 
-       //Run main program
-fld("a");
-       prStart(&flag,extension,dirName,resFile,datFilePath,datFileName,datAuthor,stdout);
-fld("b");
-       //Free memory and exit
-       if (datAuthor!=NULL) free(datAuthor);
-       if (datFileName!=NULL) free(datFileName);
-  return 0;
+       parseGivenPath(datFilePath);
+
+       /* Run main program */
+       prStart(optionflag,extension,dirName,resFile,datFilePath,datFileName,datAuthor,stdout);
+
+       /* Free memory and exit */
+       freePartialList();
+       freeAllocation(datAuthor);
+       freeAllocation(datFileName);
+       freeAllocation(datFilePath);
+       freeAllocation(extension);
+       freeAllocation(resFile);
+
+       return 0;
 }
 
 #endif
@@ -425,8 +477,9 @@ fld("b");
 \***************************************************************/
 
 #ifdef SO
-//When compiling in Unix SO libraries
+/* When compiling in Unix SO libraries */
 void start() {}
 #endif
 
 
+
index 6423b3202e28eb53cb31af6579f7dab658fe3688..2d378daf7f24524cec1069419ec871e561306987 100644 (file)
@@ -36,8 +36,9 @@ xmlsearch.c: Princed Resources : specific xml handling functions
 \***************************************************************/
 #include <stdio.h> /* only on debugging purposes */
 
-//Includes
-#include "xml.h"
+/* Includes */
+#include "pr.h"
+#include "xmlparse.h"
 #include "resources.h"
 #include "xmlsearch.h"
 #include "memory.h"
@@ -49,120 +50,62 @@ xmlsearch.c: Princed Resources : specific xml handling functions
 
 #define ptoi(p) ((p!=NULL)?atoi(p):0)
 
-tTag* searchTree(tTag* t,const char* datFile, const char* id) {
-       /* tTag*
-               tag pointer if found
-               NULL if not found
-       */
-       tTag* children;
-       tTag* result;
-
-       if (t!=NULL) {
-               if (((t->file)!=NULL)&&((t->value)!=NULL)) {
-                       if ((equalsIgnoreCase(t->file,datFile))&&(equalsIgnoreCase(t->value,id))) {
-                               return t;
-                       }
-               }
-               children=t->child;
+#define keepStringAttribute(attribute) r[id]->attribute=strallocandcopy(t->attribute)
+#define keepIntAttribute(attribute,type) r[id]->attribute=(type)ptoi(t->attribute);
 
-               while (children!=NULL) {
-                       if (NULL!=(result=searchTree(children,datFile,id))) {
-                               return result;
-                       }
-                       children=children->next;
-               }
-       }
-       return NULL;
-}
+void workTag(const tTag* t,void* pass) {
+       /*
+               If the tag matches, it is converted to resource and added to the array
+       */
 
-void workTag(const tTag* t, tResource* r[]) {
-       //Declare variables
+       /* Declare variables */
        unsigned short id;
-       unsigned short size;
-       int i;
+       const char* datFile=((tPassWork*)pass)->datFile;
+       tResource** r=((tPassWork*)pass)->r;
 
-       id=(unsigned short)ptoi(t->value);
-       if (!id) return; //If there was not id or id contained wrong values, skip
+       /* Skipping conditions */
+       if (!equalsIgnoreCase(t->file,datFile))   return; /* If it doesn't belong to the given dat file */
+       if (!(id=(unsigned short)ptoi(t->value))) return; /* If there was not id or id contained wrong values */
+       if (!equalsIgnoreCase(t->tag,"item"))     return; /* If the tag isn't an item */
 
-       //Process tag and copy values to resource
-       //Create Resource
+       /* Process tag and copy values to resource */
+       /* Create Resource */
        if (r[id]!=NULL) return;
        r[id]=(tResource*)malloc(sizeof(tResource));
        if (r[id]==NULL) return;
 
-       //Get type and palette from tag
-       if (t->itemtype==NULL) {
-               r[id]->type=0;
-       } else {
-               for (i=0;i<8;i++) if (equalsIgnoreCase(t->itemtype,getExtDesc(i))) {r[id]->type=i;break;}
-       }
-       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) {
-               size=strlen(t->external)+1;
-               r[id]->path=(char*)malloc(size);
-               if (r[id]->path!=NULL) memcpy(r[id]->path,t->external,size);
-       } else {
-               r[id]->path=NULL;
-       }
-}
-
-void workTree(const tTag* t,const char* datFile, tResource* r[]) {
-       /*
-               Runs workTag for each matching tag
-       */
-       tTag* children;
-
-       if (t!=NULL) {
-               if (t->file!=NULL) {
-                       if (equalsIgnoreCase(t->file,datFile)) {
-                               workTag(t,r);
-                       }
-               }
-               children=t->child;
-
-               while (children!=NULL) {
-                       workTree(children,datFile,r);
-                       children=children->next;
-               }
+       /* Get string itemtype and convert into the itemtypeId */
+       r[id]->type=0;
+#ifndef IGNORERESOURCEFUNCTIONS
+       if (t->itemtype!=NULL) { /* NULL tells the extractor that the type must be auto detected */
+               int i=RES_TYPECOUNT;
+               while((!r[id]->type)&&(i--))
+                       if (equalsIgnoreCase(t->itemtype,getExtDesc(i)))
+                               r[id]->type=i;
+               /* If error it returns 0 and the verifyHeader will try to detect the type */
        }
+#endif
+
+       /* Copy palette, number, title, desc and path */
+       keepIntAttribute(palette,unsigned short);  /* Transforms the char* palette into a short ID value, if 0 or error no palette is needed */
+       keepIntAttribute(number,unsigned char);    /* Transforms the char* levelnumer/number attribute into a char value, if error, demo level is used */
+       keepStringAttribute(name);  /* only for plv */
+       keepStringAttribute(desc);  /* only for plv */
+       keepStringAttribute(path);
 }
 
-void getFiles(const tTag* t) {
+void workTree(const tTag* t,void* pass, void (*function)(const tTag*,void*)) {
        /*
-               Runs addFileToList for all tags
+               Runs the given function for each matching tag
        */
        tTag* children;
 
        if (t!=NULL) {
-               if (t->file!=NULL)
-                       addFileToList(t->file);
+               if (t->file!=NULL) (*function)(t,pass);
                children=t->child;
 
                while (children!=NULL) {
-                       getFiles(children);
+                       workTree(children,pass,function);
                        children=children->next;
                }
        }
@@ -174,29 +117,25 @@ void getFiles(const tTag* t) {
 
 static tListNode* list=NULL;
 
-void addFileToList(const char* file) {
+void addFileToList(const tTag* t,void* junk) {
        /*
                Adds the file to the list only once
        */
        tListNode* node=list;
-       tListNode* old=NULL;
-       //Verify if the file exists
+
+       /* Verify if the file exists */
        while (node) {
-               if (equalsIgnoreCase(node->file,file)) //If file was in the list, do nothing
+               if (equalsIgnoreCase(node->file,t->file)) /* If file was in the list, do nothing */
                        return;
-               old=node;
                node=node->next;
        }
-       //Add new node
+       /* Add new node */
        node=(tListNode*)malloc(sizeof(tListNode));
 
-       if (old!=NULL) {
-               old->next=node;
-       } else {
-               list=node;
-       }
-       node->file=strallocandcopy(file);
-       node->next=NULL;
+       /* Use LIFO because its more probable to get a file with the same name */
+       node->file=strallocandcopy(t->file);
+       node->next=list;
+       list=node;
 }
 
 char* getFileFromList() {
@@ -206,16 +145,97 @@ char* getFileFromList() {
        char* result;
        tListNode* aux;
        if (list) {
-               //Remember node values
+               /* Remember node values */
                aux=list;
                result=list->file;
-               //move one position
+               /* move one position */
                list=list->next;
-               //free node
+               /* free node */
                free(aux);
+
                return result;
        } else {
                return NULL;
        }
-       return result;
 }
+
+/****************************************************************\
+|                       Compare two XML files                    |
+\****************************************************************/
+
+#ifdef DO_NOT_IGNORE_COMPARATION
+
+static int compareStatisticsOk=0;
+static int compareStatisticsTotals=0;
+static int compareStatisticsWarnings=0;
+extern FILE* outputStream;
+
+const tTag* searchTree(const tTag* t,const char* datFile, const char* id) {
+       /* tTag*
+               tag pointer if found
+               NULL if not found
+       */
+       tTag* children;
+       const tTag* result;
+
+       if (t!=NULL) {
+               if (((t->file)!=NULL)&&((t->value)!=NULL)) {
+                       if ((equalsIgnoreCase(t->file,datFile))&&(equalsIgnoreCase(t->value,id))) return t;
+               }
+               children=t->child;
+
+               while (children!=NULL) {
+                       if (NULL!=(result=searchTree(children,datFile,id))) {
+                               return result;
+                       }
+                       children=children->next;
+               }
+       }
+       return NULL;
+}
+
+void compareXmlFileForTag(const tTag* tag,void* pass) {
+       const tTag* modified;
+       const tTag* result;
+
+       modified=((tPassCompare*)pass)->tag;
+
+       if ((tag->file)&&(tag->value)) {
+               result=searchTree(modified,tag->file,tag->value);
+               if (!result) {
+                       fprintf(outputStream,"Error: Item not found: '%s@%s'\n",tag->value,tag->file);
+                       fprintf(outputStream,"-> <item value=\"%s\" path=\"%s\" itemtype=\"%s\" palette=\"%s\">%s</item>\n",
+                               tag->value,
+                               tag->path,
+                               tag->itemtype,
+                               tag->palette,
+                               tag->desc
+                       );
+               } else {
+                       fprintf(outputStream,"Item found: '%s@%s' %s\n",tag->value,tag->file,result->file);
+                       if (!equalsIgnoreCase(tag->itemtype,result->itemtype)) {
+                               compareStatisticsWarnings++;
+                               fprintf(outputStream,"Warning: Type mismatch in '%s@%s' (%s!=%s)\n",tag->value,tag->file,tag->itemtype,result->itemtype);
+                       }
+                       compareStatisticsOk++;
+               }
+               compareStatisticsTotals++;
+       }
+}
+
+void compareXmlFile(tTag* modified,tTag* original) {
+       tPassCompare pass;
+       pass.tag=modified;
+
+       workTree(original,&pass,compareXmlFileForTag);
+       fprintf(outputStream,"Statistics:\n Totals: %d\n Working: %d (%5.2f%%)\n Warnings: %d\n Missing: %d (%5.2f%%)\n",
+               compareStatisticsTotals,
+               compareStatisticsOk,(float)(100*(float)compareStatisticsOk/compareStatisticsTotals),
+               compareStatisticsWarnings,
+               compareStatisticsTotals-compareStatisticsOk,(float)(100*(float)(compareStatisticsTotals-compareStatisticsOk)/compareStatisticsTotals)
+       );
+}
+
+#endif
+
+
index c1bcd91823183f71516380ec6fcb1a8933845429..a49cd3418168bec6b367ee5e885e1889e596eafc 100644 (file)
@@ -35,38 +35,42 @@ resources.c: Princed Resources : Resource Handler
 |                  I M P L E M E N T A T I O N                  |
 \***************************************************************/
 
-//Includes
+/* Includes */
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include "pr.h"
-#include "xml.h"
+#include "xmlparse.h"
 #include "xmlsearch.h"
 #include "disk.h"
 #include "memory.h"
 #include "resources.h"
 #include "compress.h"
 
+extern FILE* outputStream;
+
 /***************************************************************\
-|                       File format handling                    |
+|                       Item Type Detector                      |
 \***************************************************************/
 
-int verifyLevelHeader(unsigned char* array, int size) {
+int verifyLevelHeader(const unsigned char *array, int size) {
        return (((size==2306)||(size==2305))&&!(array[1698]&0x0F)&&!(array[1700]&0x0F)&&!(array[1702]&0x0F));
 }
 
-int verifyImageHeader(unsigned char* array, int size) {
-       //return (size>6) && (!(((!array[1])||(array[2])||(!array[3])||(array[4])||(array[5])||(((unsigned char)array[6]&0xF0)!=0xB0))));
-       return (size>7) && (!array[5]) && (((unsigned char)array[6]&0xF0)==0xB0);
-       //TODO: fix the expression
+int verifyImageHeader(const unsigned char *array, int size) {
+       unsigned char imageBitRate;
+       imageBitRate=((unsigned char)array[6]&0xF0);
+       return (size>7) && (!array[5]) && ((imageBitRate==0xB0));
+       /* return (size>7) && (!array[5]) && ((imageBitRate==0xB0)||(imageBitRate==0x00)); */
 }
 
-int verifyPaletteHeader(unsigned char* array, int size) {
+int verifyPaletteHeader(const unsigned char *array, int size) {
        return ((size==101)&&(!array[2])&&(!array[3])&&(array[4]==0x10));
 }
 
-int verifyMidiHeader(unsigned char* array, int size) {
+int verifyMidiHeader(const unsigned char *array, int size) {
        return
-         (size>6) &&
+               (size>6) &&
                (array[1]==0x02) &&
                (array[2]=='M') &&
                (array[3]=='T') &&
@@ -75,26 +79,26 @@ int verifyMidiHeader(unsigned char* array, int size) {
        ;
 }
 
-int verifyWaveHeader(unsigned char* array, int size) {
+int verifyWaveHeader(const unsigned char *array, int size) {
        return
                (size>1)&&(array[1]==0x01)
        ;
 }
 
-int verifySpeakerHeader(unsigned char* array, int size) {
+int verifySpeakerHeader(const unsigned char *array, int size) {
        return
                (size>2)&&(array[1]==0x00) /* &&!(size%3) */
        ;
 }
 
-int verifyHeader(unsigned char* array, int size) {
-       if (verifyLevelHeader(array,size)) return 1;
-       if (verifyMidiHeader(array,size)) return 4;
-       if (verifyImageHeader(array,size)) return 2;
-       if (verifyPaletteHeader(array,size)) return 6;
-       if (verifyWaveHeader(array,size)) return 3;
-       if (verifySpeakerHeader(array,size)) return 7;
-       return 05;
+int verifyHeader(const unsigned char *array, int size) {
+       if (verifyLevelHeader  (array,size)) return RES_TYPE_LEVEL;
+       if (verifyMidiHeader   (array,size)) return RES_TYPE_MIDI;
+       if (verifyImageHeader  (array,size)) return RES_TYPE_IMAGE;
+       if (verifyPaletteHeader(array,size)) return RES_TYPE_PALETTE;
+       if (verifyWaveHeader   (array,size)) return RES_TYPE_WAVE;
+       if (verifySpeakerHeader(array,size)) return RES_TYPE_PCSPEAKER;
+       return RES_TYPE_BINARY;
 }
 
 const char* getExtDesc(int type) {
@@ -103,105 +107,237 @@ const char* getExtDesc(int type) {
 }
 
 /***************************************************************\
-|                      Parsing resource file                    |
+|                Partial Resource List Functions                |
+\***************************************************************/
+
+static tResIdList partialList;
+
+void parseGivenPath(char* path) {
+       /*
+               PRE:  partialList.list was not allocated
+               POST:
+                partialList.count=0 and partialList.list=NULL if all resources
+                path was trimed in the "@"
+       */
+
+       int i;
+       int separator=0;
+       int resourceValue;
+       int j=0;
+       unsigned char n;
+
+       /* Check if the variable wasn't initialized before */
+       if (partialList.count!=0) return;
+       partialList.list=NULL;
+
+       /* Validates the NULL path */
+       if (path==NULL) return;
+
+       /* Locate the string separation */
+       while (path[separator]&&path[separator]!='@') separator++;
+
+       /* If no separation */
+       if (!path[separator]) return; /* There was no separator */
+
+       /* Count values, separate them with '\0' and alloc memory */
+       partialList.count=1;
+       path[separator]=0; /* Trim the path to the separator */
+       i=++separator;
+       while(path[i]) {
+               if (path[i]==',') {
+                       partialList.count++;
+                       path[i]=0;
+               }
+               i++;
+       }