git » fp-git.git » commit 39619ea

Added better pop2 support. Less stability.

author ecalot
2005-06-03 07:33:44 UTC
committer ecalot
2005-06-03 07:33:44 UTC
parent 1369a75ad48ae9d9de2277e7688b174e254bb1d4

Added better pop2 support. Less stability.

PR/src/include/dat.h +9 -1
PR/src/include/disk.h +2 -2
PR/src/lib/actions/classify.c +5 -2
PR/src/lib/layers/dat.c +89 -18

diff --git a/PR/src/include/dat.h b/PR/src/include/dat.h
index 02fb013..7e395a5 100644
--- a/PR/src/include/dat.h
+++ b/PR/src/include/dat.h
@@ -36,7 +36,15 @@ dat.h: Princed Resources : DAT library headers
 
 #include "resources.h"
 
-#define MAX_RES_COUNT            25000
+#define MAX_RES_COUNT            65000
+
+typedef enum {
+	none=0,
+	pop1=1,
+	pop2=2
+} tPopVersion;
+
+tPopVersion mReadGetVersion();
 
 #define PR_DAT_INCLUDE_DATREAD
 #define PR_DAT_INCLUDE_DATWRITE
diff --git a/PR/src/include/disk.h b/PR/src/include/disk.h
index 1b32fdf..780fb90 100644
--- a/PR/src/include/disk.h
+++ b/PR/src/include/disk.h
@@ -91,8 +91,8 @@ int recurseDirectory(const char* path,int recursive, void* pass, void (*function
 
 /* array2vars*/
 
-#define array2short(a) ((*(a)))+((*((a)+1))<<8)
-#define array2long(a)  ((*(a)))+((*((a)+1))<<8)+((*((a)+2))<<16)+((*((a)+3))<<24)
+#define array2short(a) (((*(a)))+((*((a)+1))<<8))
+#define array2long(a)  (((*(a)))+((*((a)+1))<<8)+((*((a)+2))<<16)+((*((a)+3))<<24))
 
 #ifdef MACOS
 #define freadshort(var,file)  macfreads ((var),file)
diff --git a/PR/src/lib/actions/classify.c b/PR/src/lib/actions/classify.c
index 15033b7..c5cdd94 100644
--- a/PR/src/lib/actions/classify.c
+++ b/PR/src/lib/actions/classify.c
@@ -43,7 +43,7 @@ tasks.c: Princed Resources : Classify a DAT file
 |                    Get the type of a DAT file                 |
 \***************************************************************/
 
-extern int pop1;
+/*extern int pop1;*/
 
 #define READ_ERROR {mReadCloseDatFile();return 0;}
 
@@ -54,10 +54,13 @@ int prClassifyDat(const char* vFiledat) {
 	unsigned long  int size;
 	int                type=RES_TYPE_BINARY;
 	unsigned short int numberOfItems;
+	tPopVersion        popVersion;
 
 	/* Initialize abstract variables to read this new DAT file */
 	if ((id=mReadBeginDatFile(&numberOfItems,vFiledat))) return id+1; /* -1 if not found or empty, 0 if invalid */
 
+	popVersion=mReadGetVersion();
+
 	/* main loop */
 	for (id=0,indexNumber=0;(indexNumber<numberOfItems)&&(type==RES_TYPE_BINARY);indexNumber++) {
 		id=mReadFileInDatFile(indexNumber,&data,&size);
@@ -68,7 +71,7 @@ int prClassifyDat(const char* vFiledat) {
 	}
 
 	mReadCloseDatFile();
-	return pop1?type:(type+10);
+	return (popVersion==pop1)?type:(type+10);
 }
 
 typedef struct {
diff --git a/PR/src/lib/layers/dat.c b/PR/src/lib/layers/dat.c
index 57d05d9..40889af 100644
--- a/PR/src/lib/layers/dat.c
+++ b/PR/src/lib/layers/dat.c
@@ -47,7 +47,7 @@ dat.c: Princed Resources : DAT library
 
 char               recordSize;
 int                ofk=0;
-int                pop1;
+tPopVersion        popVersion;
 unsigned char*     indexPointer;
 unsigned long  int indexOffset;
 unsigned long  int offset;
@@ -55,6 +55,67 @@ unsigned short int indexSize;
 unsigned char*     readDatFile;
 int                readDatFileSize;
 
+/* private functions */
+
+tPopVersion detectPopVersion(int highArea,int highAreaSize) {
+	const unsigned char* cursor;
+	unsigned short numberOfRecords;
+
+	/* create cursor */
+	cursor=readDatFile+highArea;
+
+	/* read number of records */
+	numberOfRecords=array2short(cursor);cursor+=2;
+	
+	/* check pop1: if there are numberOfRecords records sized 8 and 2 bytes for the short numberOfRecords */
+	if ((numberOfRecords*8+2)==highAreaSize) {
+		indexPointer=readDatFile+highArea;
+		indexSize=highAreaSize;
+		recordSize=8;
+		return pop1;
+	}
+
+	/* check pop2: if there are numberOfRecords records sized 6 and 2 bytes for the short numberOfRecords */
+	if ((numberOfRecords*6+2)>=highAreaSize) return none;
+	printf("pop2 detected with %d high sections\n",numberOfRecords);
+	recordSize=0;
+	for (;numberOfRecords;numberOfRecords--,cursor+=6) {
+		int startOfSection;
+		int endOfSection;
+		int sizeOfSection;
+
+		/* calculate section size and offset */
+		if (numberOfRecords==1) { /* the last section size is calculated using the highAreaSize */
+			endOfSection=highAreaSize;
+		} else {
+			endOfSection=array2short(cursor+10);
+		}
+		startOfSection=array2short(cursor+4);
+		sizeOfSection=endOfSection-startOfSection;
+		
+		/* check section integrity */
+		if (sizeOfSection<0) return none;
+		
+		printf("Section %c%c%c%c starts at %d, ends at %d and length %d\n",cursor[0],cursor[1],cursor[2],cursor[3],startOfSection,endOfSection,sizeOfSection);
+		
+		/* check for the PAHS section */	
+		if (!strncmp("PAHS",(char*)cursor,4)) { /* TODO: send to define */
+			indexPointer=readDatFile+highArea+startOfSection;
+			indexSize=sizeOfSection;
+			recordSize=11;
+		}
+		
+	}
+	
+	return pop2;
+}
+
+/* public functions */
+
+tPopVersion mReadGetVersion() {
+	return popVersion;
+}
+
 void mReadCloseDatFile() {
 	free(readDatFile);
 }
@@ -72,32 +133,34 @@ int mReadBeginDatFile(unsigned short int *numberOfItems,const char* vFiledat){
 	/* Open file */
 	readDatFileSize=mLoadFileArray(vFiledat,&readDatFile);
 	if (!readDatFileSize) return -2;
-	if (readDatFileSize<=6) {free(readDatFile);return -1;}
+	if (readDatFileSize<=6) {
+		free(readDatFile);
+		return -1;
+	}
 
 	readDatFilePoint=readDatFile;
 
-	/* verify dat format */
+	/* read header  */
 	indexOffset=array2long(readDatFilePoint);
 	readDatFilePoint+=4;
 	indexSize=array2short(readDatFilePoint);
 
+	/* verify dat format: the index offset belongs to the file and the file size is the index size plus the index offset */
 	if ((indexOffset>readDatFileSize)&&((indexOffset+indexSize)!=readDatFileSize)) {
 		free(readDatFile);
 		return -1; /* this is not a valid prince dat file */
 	}
 
-	indexPointer=readDatFile+indexOffset;
+	/* read the high data to detect pop version and set up the indexPointer, indexSize and recordSize */
+	popVersion=detectPopVersion(indexOffset,indexSize);
+
+	/* pop version check */
+	if (popVersion==none) return -1;
+	if (!recordSize) {*numberOfItems=0; return 0;} /* valid dat file without an index */
+	
+	/* read numberOfItems */
 	*numberOfItems=array2short(indexPointer);
 	indexPointer+=2;
-	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);
-	} else {
-		ofk=0;
-	}
-	recordSize=pop1?8:11;
 
 	return 0;
 }
@@ -107,12 +170,20 @@ int mReadFileInDatFile(int k,unsigned char* *data,unsigned long  int *size) {
 	unsigned short int id;
 
 	/* for each archived file the index is read */
-	id=    array2short(indexPointer+ofk+k*recordSize);
-	offset=array2long(indexPointer+ofk+k*recordSize+2);
-	*size= array2short(indexPointer+ofk+k*recordSize+6)+1;
-	if ((!pop1)&&(!(indexPointer[ofk+k*recordSize+8]==0x40)&&(!indexPointer[ofk+k*recordSize+9])&&(!indexPointer[ofk+k*recordSize+10]))) return -1;
-	if (offset+indexSize>readDatFileSize) return -1;
+	id=    array2short(indexPointer+k*recordSize);
+	offset=array2long(indexPointer+k*recordSize+2);
+	*size= array2short(indexPointer+k*recordSize+6)+1;
+	
+	if ( /* pop2 integrity check */
+		(popVersion==pop2) &&
+		(!(indexPointer[k*recordSize+8]==0x40) &&
+		(!indexPointer[k*recordSize+9]) &&
+		(!indexPointer[k*recordSize+10])
+	)) return -1;
+
+	if (offset>indexOffset) return -1; /* a resourse offset is allways before the index offset */
 	*data=readDatFile+offset;
+
 	return ok?id:-1;
 }