Authors
Coding & main routines
Enrique Calot
+ Santiago Zamora
Graphic compression algorithms
Tammo Jan Dijkema
DO NOT remove this copyright notice
*/
-//Headers
+/* Headers */
#include <stdio.h>
#include <string.h>
#ifndef DLL
#ifdef UNIX
#include <unistd.h>
+ #ifndef LINUX
+ #include "getopt.h"
+ #endif
#else
#include "getopt.h"
#endif
| 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
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:
-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
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:
-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);
}
}
\***************************************************************/
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
\***************************************************************/
#ifdef SO
-//When compiling in Unix SO libraries
+/* When compiling in Unix SO libraries */
void start() {}
#endif
+
*/
/*
-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
*/
#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;
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
/*
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
#include <stdio.h>
#include <string.h>
-
#include "pr.h"
#include "extract.h"
+#include "dat.h"
#include "disk.h"
#include "memory.h"
#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;
}
+
*/
/*
-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
#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))
)
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;
}
*/
/*
-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
#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))
)
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;
}
*/
/*
-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
#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))
)
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;
}
| 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') &&
;
}
-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) {
}
/***************************************************************\
-| 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;
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
+
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++;
}
-//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
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.
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;
}
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);
}
}
-#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
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) {
/*
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;
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
+
| 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') &&
;
}
-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) {
}
/***************************************************************\
-| 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;
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
+
-#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;
}
*/
/*
-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
#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))
)
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;
}
*/
/*
-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
#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))
)
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;
}
*/
/*
-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
#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))
)
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;
}
*/
/*
-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
#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))
)
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;
}
Authors
Coding & main routines
Enrique Calot
+ Santiago Zamora
Graphic compression algorithms
Tammo Jan Dijkema
DO NOT remove this copyright notice
*/
-//Headers
+/* Headers */
#include <stdio.h>
#include <string.h>
#ifndef DLL
#ifdef UNIX
#include <unistd.h>
+ #ifndef LINUX
+ #include "getopt.h"
+ #endif
#else
#include "getopt.h"
#endif
| 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
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:
-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
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:
-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);
}
}
\***************************************************************/
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
\***************************************************************/
#ifdef SO
-//When compiling in Unix SO libraries
+/* When compiling in Unix SO libraries */
void start() {}
#endif
+
\***************************************************************/
#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"
#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;
}
}
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() {
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
+
+
| 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') &&
;
}
-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) {
}
/***************************************************************\
-| 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++;
+ }